git.s-ol.nu ~forks/DiligentCore / 8a3b697
added pipeline resource signature (wip) azhirnov 8 months ago
41 changed file(s) with 3199 addition(s) and 3701 deletion(s). Raw diff Collapse all Expand all
3030 #include "../../Platforms/interface/Atomics.hpp"
3131 #include "ValidatedCast.hpp"
3232 #include "RefCountedObjectImpl.hpp"
33
33 #include "CompilerDefinitions.h"
3434
3535 namespace Diligent
3636 {
135135 m_pObject = pObj;
136136 }
137137
138 T* Detach() noexcept
138 NODISCARD T* Detach() noexcept
139139 {
140140 T* pObj = m_pObject;
141141 m_pObject = nullptr;
2929 include/BottomLevelASBase.hpp
3030 include/TopLevelASBase.hpp
3131 include/ShaderBindingTableBase.hpp
32 include/PipelineResourceSignatureBase.hpp
3233 )
3334
3435 set(INTERFACE
4748 interface/GraphicsTypes.h
4849 interface/InputLayout.h
4950 interface/PipelineState.h
51 interface/PipelineResourceSignature.h
5052 interface/Query.h
5153 interface/RasterizerState.h
5254 interface/RenderDevice.h
494494 "Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. "
495495 "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first.");
496496
497 if (!m_pPipelineState)
498 {
499 LOG_ERROR_MESSAGE("No pipeline state is bound to the pipeline");
500 return false;
501 }
502
503 if (pShaderResourceBinding)
504 {
505 if (m_pPipelineState->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState()))
506 {
507 LOG_ERROR_MESSAGE("Shader resource binding object is not compatible with the currently bound pipeline state '", m_pPipelineState->GetDesc().Name, '\'');
508 return false;
509 }
497 if (pShaderResourceBinding == nullptr)
498 {
499 LOG_ERROR_MESSAGE("TODO");
500 return false;
510501 }
511502 #endif
512503
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 /// Implementation of the Diligent::PipelineResourceSignatureBase template class
31 #include <unordered_map>
32 #include <algorithm>
33
34 #include "PipelineResourceSignature.h"
35 #include "DeviceObjectBase.hpp"
36 #include "RenderDeviceBase.hpp"
37 #include "FixedLinearAllocator.hpp"
38
39 namespace Diligent
40 {
41
42 /// Template class implementing base functionality of the pipeline resource signature object.
43
44 /// \tparam BaseInterface - Base interface that this class will inheret
45 /// (Diligent::IPipelineResourceSignatureD3D12, Diligent::PipelineResourceSignatureVk, ...).
46 /// \tparam RenderDeviceImplType - Type of the render device implementation
47 /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl)
48 template <class BaseInterface, class RenderDeviceImplType>
49 class PipelineResourceSignatureBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, PipelineResourceSignatureDesc>
50 {
51 public:
52 using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, PipelineResourceSignatureDesc>;
53
54 /// \param pRefCounters - Reference counters object that controls the lifetime of this BLAS.
55 /// \param pDevice - Pointer to the device.
56 /// \param Desc - TLAS description.
57 /// \param bIsDeviceInternal - Flag indicating if the BLAS is an internal device object and
58 /// must not keep a strong reference to the device.
59 PipelineResourceSignatureBase(IReferenceCounters* pRefCounters,
60 RenderDeviceImplType* pDevice,
61 const PipelineResourceSignatureDesc& Desc,
62 bool bIsDeviceInternal = false) :
63 TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
64 {
65 this->m_Desc.Resources = nullptr;
66 this->m_Desc.ImmutableSamplers = nullptr;
67 }
68
69 ~PipelineResourceSignatureBase()
70 {
71 VERIFY(m_IsDestructed, "This object must be explicitly destructed with Destruct()");
72 }
73
74 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineResourceSignature, TDeviceObjectBase)
75
76 Uint32 GetVariableCount(SHADER_TYPE ShaderType) const
77 {
78 // AZ TODO: optimize
79 Uint32 Count = 0;
80 for (Uint32 i = 0; i < this->m_Desc.NumResources; ++i)
81 {
82 auto& Res = this->m_Desc.Resources[i];
83 if (Res.VarType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC && (Res.ShaderStages & ShaderType))
84 ++Count;
85 }
86 return Count;
87 }
88
89 Uint32 GetVariableGlobalIndexByName(SHADER_TYPE ShaderType, const char* Name) const
90 {
91 // AZ TODO: optimize
92 for (Uint32 i = 0; i < this->m_Desc.NumResources; ++i)
93 {
94 auto& Res = this->m_Desc.Resources[i];
95 if (Res.VarType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC && (Res.ShaderStages & ShaderType))
96 {
97 if (strcmp(Name, Res.Name) == 0)
98 return i;
99 }
100 }
101 return ~0u;
102 }
103
104 Uint32 GetVariableGlobalIndexByIndex(SHADER_TYPE ShaderType, Uint32 Index) const
105 {
106 // AZ TODO: optimize
107 Uint32 Count = 0;
108 for (Uint32 i = 0; i < this->m_Desc.NumResources; ++i)
109 {
110 auto& Res = this->m_Desc.Resources[i];
111 if (Res.VarType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC && (Res.ShaderStages & ShaderType))
112 {
113 if (Index == Count)
114 return i;
115
116 ++Count;
117 }
118 }
119 return ~0u;
120 }
121
122 Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
123 {
124 // AZ TODO: optimize
125 Uint32 Count = 0;
126 for (Uint32 i = 0; i < this->m_Desc.NumResources; ++i)
127 {
128 auto& Res = this->m_Desc.Resources[i];
129 if (Res.VarType == VarType)
130 Count += Res.ArraySize;
131 }
132 return Count;
133 }
134
135 PipelineResourceDesc GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 Index) const
136 {
137 return {};
138 }
139
140 size_t GetHash() const { return m_Hash; }
141
142 PIPELINE_TYPE GetPipelineType() const { return m_PipelineType; }
143
144 protected:
145 #define LOG_PRS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a pipeline resource signature '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)
146
147 void ReserveSpaceForDescription(FixedLinearAllocator& Allocator, const PipelineResourceSignatureDesc& Desc) noexcept(false)
148 {
149 if (Desc.NumResources == 0)
150 LOG_PRS_ERROR_AND_THROW("AZ TODO");
151
152 Allocator.AddSpace<PipelineResourceDesc>(Desc.NumResources);
153 Allocator.AddSpace<ImmutableSamplerDesc>(Desc.NumImmutableSamplers);
154
155 for (Uint32 i = 0; i < Desc.NumResources; ++i)
156 {
157 const auto& Res = Desc.Resources[i];
158
159 if (Res.Name == nullptr)
160 LOG_PRS_ERROR_AND_THROW("AZ TODO");
161
162 if (Res.ShaderStages == SHADER_TYPE_UNKNOWN)
163 LOG_PRS_ERROR_AND_THROW("AZ TODO");
164
165 if (Res.ArraySize == 0)
166 LOG_PRS_ERROR_AND_THROW("AZ TODO");
167
168 Allocator.AddSpaceForString(Res.Name);
169 }
170
171 for (Uint32 i = 0; i < Desc.NumImmutableSamplers; ++i)
172 {
173 if (Desc.ImmutableSamplers[i].SamplerOrTextureName == nullptr)
174 LOG_PRS_ERROR_AND_THROW("AZ TODO");
175
176 Allocator.AddSpaceForString(Desc.ImmutableSamplers[i].SamplerOrTextureName);
177 }
178 }
179
180 void CopyDescription(FixedLinearAllocator& Allocator, const PipelineResourceSignatureDesc& Desc) noexcept(false)
181 {
182 PipelineResourceDesc* pResources = Allocator.Allocate<PipelineResourceDesc>(this->m_Desc.NumResources);
183 ImmutableSamplerDesc* pSamplers = Allocator.Allocate<ImmutableSamplerDesc>(this->m_Desc.NumImmutableSamplers);
184
185 m_Hash = ComputeHash(Desc.NumResources, Desc.NumImmutableSamplers);
186
187 for (Uint32 i = 0; i < Desc.NumResources; ++i)
188 {
189 auto& Dst = pResources[i];
190 Dst = Desc.Resources[i];
191 Dst.Name = Allocator.CopyString(Desc.Resources[i].Name);
192
193 HashCombine(m_Hash, CStringHash<char>{}(Dst.Name), Dst.ArraySize, Dst.ResourceType, Dst.ShaderStages, Dst.VarType, Dst.Flags);
194 }
195
196 for (Uint32 i = 0; i < Desc.NumImmutableSamplers; ++i)
197 {
198 auto& Dst = pSamplers[i];
199 Dst = Desc.ImmutableSamplers[i];
200 Dst.SamplerOrTextureName = Allocator.CopyString(Desc.ImmutableSamplers[i].SamplerOrTextureName);
201
202 //HashCombine(m_Hash, CStringHash<char>{}(Dst.Name), Dst.ShaderStages, Dst.Desc); // AZ TODO
203 }
204
205 this->m_Desc.Resources = pResources;
206 this->m_Desc.ImmutableSamplers = pSamplers;
207 }
208
209 void Destruct()
210 {
211 VERIFY(!m_IsDestructed, "This object has already been destructed");
212
213 this->m_Desc.Resources = nullptr;
214 this->m_Desc.ImmutableSamplers = nullptr;
215
216 #if DILIGENT_DEBUG
217 m_IsDestructed = true;
218 #endif
219 }
220
221 #undef LOG_PRS_ERROR_AND_THROW
222
223 Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& StaticVarIndex) const
224 {
225 if (!IsConsistentShaderType(ShaderType, m_PipelineType))
226 {
227 LOG_WARNING_MESSAGE("Unable to get the number of static variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
228 " as the stage is invalid for ", GetPipelineTypeString(m_PipelineType), " pipeline resource signature '", this->m_Desc.Name, "'.");
229 return -1;
230 }
231
232 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_PipelineType);
233 const auto LayoutInd = StaticVarIndex[ShaderTypeInd];
234 if (LayoutInd < 0)
235 {
236 LOG_WARNING_MESSAGE("Unable to get the number of static variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
237 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
238 }
239
240 return LayoutInd;
241 }
242
243 Int8 GetStaticVariableByNameHelper(SHADER_TYPE ShaderType, const Char* Name, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& StaticVarIndex) const
244 {
245 if (!IsConsistentShaderType(ShaderType, m_PipelineType))
246 {
247 LOG_WARNING_MESSAGE("Unable to find static variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
248 " as the stage is invalid for ", GetPipelineTypeString(m_PipelineType), " pipeline resource signature '", this->m_Desc.Name, "'.");
249 return -1;
250 }
251
252 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_PipelineType);
253 const auto LayoutInd = StaticVarIndex[ShaderTypeInd];
254 if (LayoutInd < 0)
255 {
256 LOG_WARNING_MESSAGE("Unable to find static variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
257 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
258 }
259
260 return LayoutInd;
261 }
262
263 Int8 GetStaticVariableByIndexHelper(SHADER_TYPE ShaderType, Uint32 Index, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& StaticVarIndex) const
264 {
265 if (!IsConsistentShaderType(ShaderType, m_PipelineType))
266 {
267 LOG_WARNING_MESSAGE("Unable to get static variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
268 " as the stage is invalid for ", GetPipelineTypeString(m_PipelineType), " pipeline resource signature '", this->m_Desc.Name, "'.");
269 return -1;
270 }
271
272 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_PipelineType);
273 const auto LayoutInd = StaticVarIndex[ShaderTypeInd];
274 if (LayoutInd < 0)
275 {
276 LOG_WARNING_MESSAGE("Unable to get static variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
277 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
278 }
279
280 return LayoutInd;
281 }
282
283 protected:
284 size_t m_Hash = 0;
285
286 PIPELINE_TYPE m_PipelineType = PIPELINE_TYPE(0xFF);
287
288 #ifdef DILIGENT_DEBUG
289 bool m_IsDestructed = false;
290 #endif
291 };
292
293 } // namespace Diligent
222222 // it can potentially give false negatives
223223 bool IsIncompatibleWith(const IPipelineState* pPSO) const
224224 {
225 return m_ShaderResourceLayoutHash != ValidatedCast<const PipelineStateBase>(pPSO)->m_ShaderResourceLayoutHash;
225 return false;
226 //return m_ShaderResourceLayoutHash != ValidatedCast<const PipelineStateBase>(pPSO)->m_ShaderResourceLayoutHash;
226227 }
227228
228229 virtual const GraphicsPipelineDesc& DILIGENT_CALL_TYPE GetGraphicsPipelineDesc() const override final
239240 return m_pRayTracingPipelineData->Desc;
240241 }
241242
243 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
244 bool InitStaticResources) override final
245 {
246 auto* pSign = GetResourceSignature(0);
247 if (pSign)
248 return pSign->CreateShaderResourceBinding(ppShaderResourceBinding, InitStaticResources);
249 }
250
251 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType,
252 const Char* Name) override final
253 {
254 VERIFY_EXPR(GetResourceSignatureCount() == 1);
255
256 auto* pSign = GetResourceSignature(0);
257 if (pSign)
258 return pSign->GetStaticVariableByName(ShaderType, Name);
259
260 return nullptr;
261 }
262
263 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType,
264 Uint32 Index) override final
265 {
266 VERIFY_EXPR(GetResourceSignatureCount() == 1);
267
268 auto* pSign = GetResourceSignature(0);
269 if (pSign)
270 return pSign->GetStaticVariableByIndex(ShaderType, Index);
271
272 return nullptr;
273 }
274
275 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final
276 {
277 VERIFY_EXPR(GetResourceSignatureCount() == 1);
278
279 auto* pSign = GetResourceSignature(0);
280 if (pSign)
281 return pSign->GetStaticVariableCount(ShaderType);
282
283 return 0;
284 }
285
242286 inline void CopyShaderHandle(const char* Name, void* pData, size_t DataSize) const
243287 {
244288 VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline());
266310
267311 protected:
268312 using TNameToGroupIndexMap = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>;
269
270 Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
271 {
272 if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType))
273 {
274 LOG_WARNING_MESSAGE("Unable to get the number of static variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
275 " as the stage is invalid for ", GetPipelineTypeString(this->m_Desc.PipelineType), " pipeline '", this->m_Desc.Name, "'.");
276 return -1;
277 }
278
279 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, this->m_Desc.PipelineType);
280 const auto LayoutInd = ResourceLayoutIndex[ShaderTypeInd];
281 if (LayoutInd < 0)
282 {
283 LOG_WARNING_MESSAGE("Unable to get the number of static variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
284 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
285 }
286
287 return LayoutInd;
288 }
289
290 Int8 GetStaticVariableByNameHelper(SHADER_TYPE ShaderType, const Char* Name, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
291 {
292 if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType))
293 {
294 LOG_WARNING_MESSAGE("Unable to find static variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
295 " as the stage is invalid for ", GetPipelineTypeString(this->m_Desc.PipelineType), " pipeline '", this->m_Desc.Name, "'.");
296 return -1;
297 }
298
299 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, this->m_Desc.PipelineType);
300 const auto LayoutInd = ResourceLayoutIndex[ShaderTypeInd];
301 if (LayoutInd < 0)
302 {
303 LOG_WARNING_MESSAGE("Unable to find static variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
304 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
305 }
306
307 return LayoutInd;
308 }
309
310 Int8 GetStaticVariableByIndexHelper(SHADER_TYPE ShaderType, Uint32 Index, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
311 {
312 if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType))
313 {
314 LOG_WARNING_MESSAGE("Unable to get static variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
315 " as the stage is invalid for ", GetPipelineTypeString(this->m_Desc.PipelineType), " pipeline '", this->m_Desc.Name, "'.");
316 return -1;
317 }
318
319 const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, this->m_Desc.PipelineType);
320 const auto LayoutInd = ResourceLayoutIndex[ShaderTypeInd];
321 if (LayoutInd < 0)
322 {
323 LOG_WARNING_MESSAGE("Unable to get static variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
324 " as the stage is inactive in PSO '", this->m_Desc.Name, "'.");
325 }
326
327 return LayoutInd;
328 }
329
330313
331314 void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo,
332315 FixedLinearAllocator& MemPool) noexcept
745728 }
746729
747730 protected:
748 size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
749
750731 Uint32* m_pStrides = nullptr;
751732 Uint8 m_BufferSlotsUsed = 0;
752733
234234
235235 /// Size of the SBT object (ShaderBindingTableD3D12Impl, ShaderBindingtableVkImpl, etc.), in bytes
236236 const size_t SBTObjSize;
237
238 /// AZ TODO: comment
239 const size_t PipeResSignObjSize;
237240 };
238241
239242 /// \param pRefCounters - Reference counters object that controls the lifetime of this render device
273276 m_BLASAllocator {RawMemAllocator, ObjectSizes.BLASObjSize, 16 },
274277 m_TLASAllocator {RawMemAllocator, ObjectSizes.TLASObjSize, 16 },
275278 m_SBTAllocator {RawMemAllocator, ObjectSizes.SBTObjSize, 16 },
279 m_PipeResSignAllocator {RawMemAllocator, ObjectSizes.PipeResSignObjSize, 128 },
276280 m_DeviceProperties {}
277281 // clang-format on
278282 {
458462 FixedBlockMemoryAllocator m_BLASAllocator; ///< Allocator for bottom-level acceleration structure objects
459463 FixedBlockMemoryAllocator m_TLASAllocator; ///< Allocator for top-level acceleration structure objects
460464 FixedBlockMemoryAllocator m_SBTAllocator; ///< Allocator for shader binding table objects
465 FixedBlockMemoryAllocator m_PipeResSignAllocator; ///< Allocator for pipeline resource signature objects
461466 };
462467
463468
4646 /// \tparam BaseInterface - Base interface that this class will inheret
4747 /// (Diligent::IShaderResourceBindingGL, Diligent::IShaderResourceBindingD3D11,
4848 /// Diligent::IShaderResourceBindingD3D12 or Diligent::IShaderResourceBindingVk).
49 /// \tparam PipelineStateImplType - Type of the pipeline state implementation
50 /// (Diligent::PipelineStateD3D12Impl, Diligent::PipelineStateVkImpl, etc.)
51 template <class BaseInterface, class PipelineStateImplType>
49 /// \tparam ResourceSignatureType - Type of the pipeline resource signature implementation
50 /// (Diligent::PipelineResourceSignatureD3D12Impl, Diligent::PipelineResourceSignatureVkImpl, etc.)
51 template <class BaseInterface, class ResourceSignatureType>
5252 class ShaderResourceBindingBase : public ObjectBase<BaseInterface>
5353 {
5454 public:
5555 typedef ObjectBase<BaseInterface> TObjectBase;
5656
5757 /// \param pRefCounters - Reference counters object that controls the lifetime of this SRB.
58 /// \param pPSO - Pipeline state that this SRB belongs to.
59 /// \param IsInternal - Flag indicating if the shader resource binding is an internal PSO object and
60 /// must not keep a strong reference to the PSO.
61 ShaderResourceBindingBase(IReferenceCounters* pRefCounters, PipelineStateImplType* pPSO, bool IsInternal = false) :
58 /// \param pPRS - Pipeline resource signature that this SRB belongs to.
59 /// \param IsInternal - Flag indicating if the shader resource binding is an internal object and
60 /// must not keep a strong reference to the pipeline resource signature.
61 ShaderResourceBindingBase(IReferenceCounters* pRefCounters, ResourceSignatureType* pPRS, bool IsInternal = false) :
6262 TObjectBase{pRefCounters},
63 m_spPSO{IsInternal ? nullptr : pPSO},
64 m_pPSO{pPSO}
63 m_spPRS{IsInternal ? nullptr : pPRS},
64 m_pPRS{pPRS}
6565 {}
6666
6767 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBinding, TObjectBase)
6868
6969 /// Implementation of IShaderResourceBinding::GetPipelineState().
70 virtual IPipelineState* DILIGENT_CALL_TYPE GetPipelineState() override final
70 //virtual IPipelineState* DILIGENT_CALL_TYPE GetPipelineState() override final
71 //{
72 // return m_pPSO;
73 //}
74
75 //template <typename PSOType>
76 //PSOType* GetPipelineState()
77 //{
78 // return ValidatedCast<PSOType>(m_pPSO);
79 //}
80
81 //template <typename PSOType>
82 //PSOType* GetPipelineState() const
83 //{
84 // return ValidatedCast<PSOType>(m_pPSO);
85 //}
86
87 Uint32 GetBindingIndex() const
7188 {
72 return m_pPSO;
89 return m_pPRS->GetDesc().BindingIndex;
7390 }
7491
75 template <typename PSOType>
76 PSOType* GetPipelineState()
92 PIPELINE_TYPE GetPipelineType() const
7793 {
78 return ValidatedCast<PSOType>(m_pPSO);
94 return ValidatedCast<ResourceSignatureType>(m_pPRS)->GetPipelineType();
7995 }
8096
81 template <typename PSOType>
82 PSOType* GetPipelineState() const
97 /// Implementation of IShaderResourceBinding::GetPipelineResourceSignature().
98 virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetPipelineResourceSignature() override final
8399 {
84 return ValidatedCast<PSOType>(m_pPSO);
100 return m_pPRS;
101 }
102
103 ResourceSignatureType* GetSignature() const
104 {
105 return ValidatedCast<ResourceSignatureType>(m_pPRS);
85106 }
86107
87108 protected:
88109 Int8 GetVariableByNameHelper(SHADER_TYPE ShaderType, const char* Name, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
89110 {
90 const auto PipelineType = m_pPSO->GetDesc().PipelineType;
111 const auto PipelineType = GetPipelineType();
91112 if (!IsConsistentShaderType(ShaderType, PipelineType))
92113 {
93114 LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
94 " as the stage is invalid for ", GetPipelineTypeString(m_pPSO->GetDesc().PipelineType), " pipeline '", m_pPSO->GetDesc().Name, "'.");
115 " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
95116 return -1;
96117 }
97118
100121 if (ResLayoutInd < 0)
101122 {
102123 LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
103 " as the stage is inactive in PSO '", m_pPSO->GetDesc().Name, "'.");
124 " as the stage is inactive in pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
104125 }
105126
106127 return ResLayoutInd;
108129
109130 Int8 GetVariableCountHelper(SHADER_TYPE ShaderType, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
110131 {
111 const auto PipelineType = m_pPSO->GetDesc().PipelineType;
132 const auto PipelineType = GetPipelineType();
112133 if (!IsConsistentShaderType(ShaderType, PipelineType))
113134 {
114135 LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
115 " as the stage is invalid for ", GetPipelineTypeString(m_pPSO->GetDesc().PipelineType), " pipeline '", m_pPSO->GetDesc().Name, "'.");
136 " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
116137 return -1;
117138 }
118139
121142 if (ResLayoutInd < 0)
122143 {
123144 LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
124 " as the stage is inactive in PSO '", m_pPSO->GetDesc().Name, "'.");
145 " as the stage is inactive in pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
125146 }
126147
127148 return ResLayoutInd;
129150
130151 Int8 GetVariableByIndexHelper(SHADER_TYPE ShaderType, Uint32 Index, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
131152 {
132 const auto PipelineType = m_pPSO->GetDesc().PipelineType;
153 const auto PipelineType = GetPipelineType();
133154 if (!IsConsistentShaderType(ShaderType, PipelineType))
134155 {
135156 LOG_WARNING_MESSAGE("Unable to get mutable/dynamic variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
136 " as the stage is invalid for ", GetPipelineTypeString(m_pPSO->GetDesc().PipelineType), " pipeline '", m_pPSO->GetDesc().Name, "'.");
157 " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
137158 return -1;
138159 }
139160
142163 if (ResLayoutInd < 0)
143164 {
144165 LOG_WARNING_MESSAGE("Unable to get mutable/dynamic variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
145 " as the stage is inactive in PSO '", m_pPSO->GetDesc().Name, "'.");
166 " as the stage is inactive in pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
146167 }
147168
148169 return ResLayoutInd;
149170 }
150171
151 /// Strong reference to PSO. We must use strong reference, because
152 /// shader resource binding uses PSO's memory allocator to allocate
172 protected:
173 /// Strong reference to pipeline resource signature. We must use strong reference, because
174 /// shader resource binding uses pipeline resource signature's memory allocator to allocate
153175 /// memory for shader resource cache.
154 RefCntAutoPtr<PipelineStateImplType> m_spPSO;
155 PipelineStateImplType* const m_pPSO;
176 RefCntAutoPtr<ResourceSignatureType> m_spPRS;
177
178 IPipelineResourceSignature* m_pPRS = nullptr;
156179 };
157180
158181 } // namespace Diligent
5353 /// (Vertex, Hull, Domain, Geometry, Pixel) or (Amplification, Mesh, Pixel), or (Compute) or (RayGen, Miss, ClosestHit, AnyHit, Intersection, Callable)
5454 static const Uint32 MAX_SHADERS_IN_PIPELINE = 6;
5555
56 static const Uint32 MAX_RESOURCE_SIGNATURES = 8;
57
5658 // clang-format on
5759
5860 DILIGENT_END_NAMESPACE // namespace Diligent
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 // clang-format off
30
31 /// \file
32 /// Definition of the Diligent::IRenderDevice interface and related data structures
33
34 #include "../../../Primitives/interface/Object.h"
35 #include "../../../Platforms/interface/PlatformDefinitions.h"
36 #include "GraphicsTypes.h"
37 #include "Shader.h"
38 #include "Sampler.h"
39 #include "ShaderResourceVariable.h"
40 #include "ShaderResourceBinding.h"
41
42 DILIGENT_BEGIN_NAMESPACE(Diligent)
43
44
45 /// Immutable sampler description.
46
47 /// An immutable sampler is compiled into the pipeline state and can't be changed.
48 /// It is generally more efficient than a regular sampler and should be used
49 /// whenever possible.
50 struct ImmutableSamplerDesc
51 {
52 /// Shader stages that this immutable sampler applies to. More than one shader stage can be specified.
53 SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
54
55 /// The name of the sampler itself or the name of the texture variable that
56 /// this immutable sampler is assigned to if combined texture samplers are used.
57 const Char* SamplerOrTextureName DEFAULT_INITIALIZER(nullptr);
58
59 /// Sampler description
60 struct SamplerDesc Desc;
61
62 #if DILIGENT_CPP_INTERFACE
63 ImmutableSamplerDesc()noexcept{}
64
65 ImmutableSamplerDesc(SHADER_TYPE _ShaderStages,
66 const Char* _SamplerOrTextureName,
67 const SamplerDesc& _Desc)noexcept :
68 ShaderStages {_ShaderStages },
69 SamplerOrTextureName{_SamplerOrTextureName},
70 Desc {_Desc }
71 {}
72 #endif
73 };
74 typedef struct ImmutableSamplerDesc ImmutableSamplerDesc;
75
76
77 /// AZ TODO: comment
78 DILIGENT_TYPED_ENUM(PIPELINE_RESOURCE_FLAGS, Uint8)
79 {
80 PIPELINE_RESOURCE_FLAG_UNKNOWN = 0x00,
81 PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_OFFSETS = 0x01, ///< Vulkan only, for SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_TYPE_BUFFER_UAV, SHADER_RESOURCE_TYPE_BUFFER_SRV
82 PIPELINE_RESOURCE_FLAG_COMBINED_IMAGE = 0x02, ///< For SHADER_RESOURCE_TYPE_TEXTURE_SRV
83 PIPELINE_RESOURCE_FLAG_TEXEL_BUFFER = 0x04, ///< For SHADER_RESOURCE_TYPE_BUFFER_UAV, SHADER_RESOURCE_TYPE_BUFFER_SRV
84 };
85 DEFINE_FLAG_ENUM_OPERATORS(PIPELINE_RESOURCE_FLAGS);
86
87
88 /// AZ TODO: comment
89 struct PipelineResourceDesc
90 {
91 /// AZ TODO: comment
92 const char* Name DEFAULT_INITIALIZER(nullptr);
93
94 /// AZ TODO: comment
95 SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
96
97 /// AZ TODO: comment
98 Uint32 ArraySize DEFAULT_INITIALIZER(1);
99
100 /// AZ TODO: comment
101 SHADER_RESOURCE_TYPE ResourceType DEFAULT_INITIALIZER(SHADER_RESOURCE_TYPE_UNKNOWN);
102
103 /// AZ TODO: comment
104 SHADER_RESOURCE_VARIABLE_TYPE VarType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE);
105
106 /// AZ TODO: comment
107 PIPELINE_RESOURCE_FLAGS Flags DEFAULT_INITIALIZER(PIPELINE_RESOURCE_FLAG_UNKNOWN);
108
109 /// AZ TODO: comment
110 RESOURCE_DIMENSION ResourceDim DEFAULT_INITIALIZER(RESOURCE_DIM_UNDEFINED);
111
112 #if DILIGENT_CPP_INTERFACE
113 PipelineResourceDesc()noexcept{}
114
115 PipelineResourceDesc(const char* _Name,
116 Uint32 _ArraySize,
117 SHADER_RESOURCE_TYPE _ResourceType,
118 SHADER_TYPE _ShaderStages,
119 SHADER_RESOURCE_VARIABLE_TYPE _VarType,
120 RESOURCE_DIMENSION _Dim = RESOURCE_DIM_UNDEFINED,
121 PIPELINE_RESOURCE_FLAGS _Flags = PIPELINE_RESOURCE_FLAG_UNKNOWN)noexcept :
122 Name {_Name },
123 ArraySize {_ArraySize },
124 ResourceType{_ResourceType},
125 ShaderStages{_ShaderStages},
126 VarType {_VarType },
127 Flags {_Flags },
128 ResourceDim {_Dim }
129 {}
130 #endif
131 };
132 typedef struct PipelineResourceDesc PipelineResourceDesc;
133
134
135 /// AZ TODO: comment
136 struct PipelineResourceSignatureDesc DILIGENT_DERIVE(DeviceObjectAttribs)
137
138 /// AZ TODO: comment
139 const PipelineResourceDesc* Resources DEFAULT_INITIALIZER(nullptr);
140
141 /// AZ TODO: comment
142 Uint32 NumResources DEFAULT_INITIALIZER(0);
143
144 /// AZ TODO: comment
145 const ImmutableSamplerDesc* ImmutableSamplers DEFAULT_INITIALIZER(nullptr);
146
147 /// AZ TODO: comment
148 Uint32 NumImmutableSamplers DEFAULT_INITIALIZER(0);
149
150 /// AZ TODO: comment
151 Uint8 BindingIndex DEFAULT_INITIALIZER(0);
152
153 /// AZ TODO: comment
154 Uint16 BindingOffsets [SHADER_RESOURCE_TYPE_LAST + 1] DEFAULT_INITIALIZER({});
155
156 /// Shader resource binding allocation granularity
157
158 /// This member defines allocation granularity for internal resources required by the shader resource
159 /// binding object instances.
160 Uint32 SRBAllocationGranularity DEFAULT_INITIALIZER(1);
161 };
162 typedef struct PipelineResourceSignatureDesc PipelineResourceSignatureDesc;
163
164
165 // {DCE499A5-F812-4C93-B108-D684A0B56118}
166 static const INTERFACE_ID IID_PipelineResourceSignature =
167 {0xdce499a5, 0xf812, 0x4c93, {0xb1, 0x8, 0xd6, 0x84, 0xa0, 0xb5, 0x61, 0x18}};
168
169 #define DILIGENT_INTERFACE_NAME IPipelineResourceSignature
170 #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
171
172 #define IPipelineResourceSignatureInclusiveMethods \
173 IDeviceObjectInclusiveMethods; \
174 IPipelineResourceSignatureMethods PipelineResourceSignature
175
176 // clang-format off
177
178 /// Pipeline state interface
179 DILIGENT_BEGIN_INTERFACE(IPipelineResourceSignature, IDeviceObject)
180 {
181 #if DILIGENT_CPP_INTERFACE
182 /// AZ TODO: comment
183 virtual const PipelineResourceSignatureDesc& METHOD(GetDesc)() const override = 0;
184 #endif
185
186 /// Creates a shader resource binding object
187
188 /// \param [out] ppShaderResourceBinding - memory location where pointer to the new shader resource
189 /// binding object is written.
190 /// \param [in] InitStaticResources - if set to true, the method will initialize static resources in
191 /// the created object, which has the exact same effect as calling
192 /// IShaderResourceBinding::InitializeStaticResources().
193 VIRTUAL void METHOD(CreateShaderResourceBinding)(THIS_
194 IShaderResourceBinding** ppShaderResourceBinding,
195 bool InitStaticResources DEFAULT_VALUE(false)) PURE;
196
197
198 /// Returns static shader resource variable. If the variable is not found,
199 /// returns nullptr.
200
201 /// \param [in] ShaderType - Type of the shader to look up the variable.
202 /// Must be one of Diligent::SHADER_TYPE.
203 /// \param [in] Name - Name of the variable.
204 /// \remark The method does not increment the reference counter
205 /// of the returned interface.
206 VIRTUAL IShaderResourceVariable* METHOD(GetStaticVariableByName)(THIS_
207 SHADER_TYPE ShaderType,
208 const Char* Name) PURE;
209
210
211 /// Returns static shader resource variable by its index.
212
213 /// \param [in] ShaderType - Type of the shader to look up the variable.
214 /// Must be one of Diligent::SHADER_TYPE.
215 /// \param [in] Index - Shader variable index. The index must be between
216 /// 0 and the total number of variables returned by
217 /// GetStaticVariableCount().
218 /// \remark Only static shader resource variables can be accessed through this method.
219 /// Mutable and dynamic variables are accessed through Shader Resource
220 /// Binding object
221 VIRTUAL IShaderResourceVariable* METHOD(GetStaticVariableByIndex)(THIS_
222 SHADER_TYPE ShaderType,
223 Uint32 Index) PURE;
224
225
226 /// Returns the number of static shader resource variables.
227
228 /// \param [in] ShaderType - Type of the shader.
229 /// \remark Only static variables (that can be accessed directly through the PSO) are counted.
230 /// Mutable and dynamic variables are accessed through Shader Resource Binding object.
231 VIRTUAL Uint32 METHOD(GetStaticVariableCount)(THIS_
232 SHADER_TYPE ShaderType) CONST PURE;
233 };
234 DILIGENT_END_INTERFACE
235
236 #include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
237
238 #if DILIGENT_C_INTERFACE
239
240 // clang-format off
241
242 # define IPipelineResourceSignature_GetDesc(This) (const struct PipelineResourceSignatureDesc*)IDeviceObject_GetDesc(This)
243
244 # define IPipelineResourceSignature_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineResourceSignature, CreateShaderResourceBinding, This, __VA_ARGS__)
245 # define IPipelineResourceSignature_GetStaticVariableByName(This, ...) CALL_IFACE_METHOD(PipelineResourceSignature, GetStaticVariableByName, This, __VA_ARGS__)
246 # define IPipelineResourceSignature_GetStaticVariableByIndex(This, ...) CALL_IFACE_METHOD(PipelineResourceSignature, GetStaticVariableByIndex, This, __VA_ARGS__)
247 # define IPipelineResourceSignature_GetStaticVariableCount(This, ...) CALL_IFACE_METHOD(PipelineResourceSignature, GetStaticVariableCount, This, __VA_ARGS__)
248
249 // clang-format on
250
251 #endif
252
253 DILIGENT_END_NAMESPACE
4343 #include "Shader.h"
4444 #include "Sampler.h"
4545 #include "RenderPass.h"
46 #include "PipelineResourceSignature.h"
4647
4748 DILIGENT_BEGIN_NAMESPACE(Diligent)
4849
9495 };
9596 typedef struct ShaderResourceVariableDesc ShaderResourceVariableDesc;
9697
97
98 /// Immutable sampler description.
99
100 /// An immutable sampler is compiled into the pipeline state and can't be changed.
101 /// It is generally more efficient than a regular sampler and should be used
102 /// whenever possible.
103 struct ImmutableSamplerDesc
104 {
105 /// Shader stages that this immutable sampler applies to. More than one shader stage can be specified.
106 SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
107
108 /// The name of the sampler itself or the name of the texture variable that
109 /// this immutable sampler is assigned to if combined texture samplers are used.
110 const Char* SamplerOrTextureName DEFAULT_INITIALIZER(nullptr);
111
112 /// Sampler description
113 struct SamplerDesc Desc;
114
115 #if DILIGENT_CPP_INTERFACE
116 ImmutableSamplerDesc()noexcept{}
117
118 ImmutableSamplerDesc(SHADER_TYPE _ShaderStages,
119 const Char* _SamplerOrTextureName,
120 const SamplerDesc& _Desc)noexcept :
121 ShaderStages {_ShaderStages },
122 SamplerOrTextureName{_SamplerOrTextureName},
123 Desc {_Desc }
124 {}
125 #endif
126 };
127 typedef struct ImmutableSamplerDesc ImmutableSamplerDesc;
12898
12999 /// Pipeline layout description
130100 struct PipelineResourceLayoutDesc
395365
396366 /// Pipeline state creation flags, see Diligent::PSO_CREATE_FLAGS.
397367 PSO_CREATE_FLAGS Flags DEFAULT_INITIALIZER(PSO_CREATE_FLAG_NONE);
368
369 /// AZ TODO
370 IPipelineResourceSignature** ppResourceSignatures DEFAULT_INITIALIZER(nullptr);
371
372 /// AZ TODO
373 Uint32 ResourceSignaturesCount DEFAULT_INITIALIZER(0);
398374 };
399375 typedef struct PipelineStateCreateInfo PipelineStateCreateInfo;
400376
522498 /// Returns the ray tracing pipeline description used to create the object.
523499 /// This method must only be called for a ray tracing pipeline.
524500 VIRTUAL const RayTracingPipelineDesc REF METHOD(GetRayTracingPipelineDesc)(THIS) CONST PURE;
501
525502
526503 /// Binds resources for all shaders in the pipeline state
527504
534511 IResourceMapping* pResourceMapping,
535512 Uint32 Flags) PURE;
536513
537
514
538515 /// Returns the number of static shader resource variables.
516 /// Deprecated: use GetResourceSignature() and call IPipelineResourceSignature::GetStaticVariableCount().
539517
540518 /// \param [in] ShaderType - Type of the shader.
541519 /// \remark Only static variables (that can be accessed directly through the PSO) are counted.
543521 VIRTUAL Uint32 METHOD(GetStaticVariableCount)(THIS_
544522 SHADER_TYPE ShaderType) CONST PURE;
545523
546
524
547525 /// Returns static shader resource variable. If the variable is not found,
548526 /// returns nullptr.
527 /// Deprecated: use GetResourceSignature() and call IPipelineResourceSignature::GetStaticVariableByName().
549528
550529 /// \param [in] ShaderType - Type of the shader to look up the variable.
551530 /// Must be one of Diligent::SHADER_TYPE.
556535 SHADER_TYPE ShaderType,
557536 const Char* Name) PURE;
558537
559
538
560539 /// Returns static shader resource variable by its index.
540 /// Deprecated: use GetResourceSignature() and call IPipelineResourceSignature::GetStaticVariableByIndex().
561541
562542 /// \param [in] ShaderType - Type of the shader to look up the variable.
563543 /// Must be one of Diligent::SHADER_TYPE.
572552 Uint32 Index) PURE;
573553
574554
575 /// Creates a shader resource binding object
555 /// Creates a shader resource binding object.
556 /// Deprecated: use GetResourceSignature() and call IPipelineResourceSignature::CreateShaderResourceBinding().
576557
577558 /// \param [out] ppShaderResourceBinding - memory location where pointer to the new shader resource
578559 /// binding object is written.
600581 /// into account vertex shader input layout, number of outputs, etc.
601582 VIRTUAL bool METHOD(IsCompatibleWith)(THIS_
602583 const struct IPipelineState* pPSO) CONST PURE;
584
585
586 /// AZ TODO: comment
587 VIRTUAL Uint32 METHOD(GetResourceSignatureCount)(THIS) CONST PURE;
588
589 /// AZ TODO: comment
590 VIRTUAL IPipelineResourceSignature* METHOD(GetResourceSignature)(THIS_
591 Uint32 Index) CONST PURE;
603592 };
604593 DILIGENT_END_INTERFACE
605594
619608 # define IPipelineState_GetStaticVariableByIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByIndex, This, __VA_ARGS__)
620609 # define IPipelineState_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineState, CreateShaderResourceBinding, This, __VA_ARGS__)
621610 # define IPipelineState_IsCompatibleWith(This, ...) CALL_IFACE_METHOD(PipelineState, IsCompatibleWith, This, __VA_ARGS__)
611 # define IPipelineState_GetResourceSignatureCount(This) CALL_IFACE_METHOD(PipelineState, GetResourceSignatureCount, This)
612 # define IPipelineState_GetResourceSignature(This, ...) CALL_IFACE_METHOD(PipelineState, GetResourceSignature, This, __VA_ARGS__)
622613
623614 // clang-format on
624615
4949 #include "BottomLevelAS.h"
5050 #include "TopLevelAS.h"
5151 #include "ShaderBindingTable.h"
52 #include "PipelineResourceSignature.h"
5253
5354 #include "DepthStencilState.h"
5455 #include "RasterizerState.h"
272273 const ShaderBindingTableDesc REF Desc,
273274 IShaderBindingTable** ppSBT) PURE;
274275
276 /// AZ TODO: comment
277 VIRTUAL void METHOD(CreatePipelineResourceSignature)(THIS_
278 const PipelineResourceSignatureDesc REF Desc,
279 IPipelineResourceSignature** ppSignature) PURE;
280
275281
276282 /// Gets the device capabilities, see Diligent::DeviceCaps for details
277283 VIRTUAL const DeviceCaps REF METHOD(GetDeviceCaps)(THIS) CONST PURE;
3737 DILIGENT_BEGIN_NAMESPACE(Diligent)
3838
3939 struct IPipelineState;
40 struct IPipelineResourceSignature;
4041
4142 // {061F8774-9A09-48E8-8411-B5BD20560104}
4243 static const INTERFACE_ID IID_ShaderResourceBinding =
5556 /// Shader resource binding interface
5657 DILIGENT_BEGIN_INTERFACE(IShaderResourceBinding, IObject)
5758 {
58 /// Returns pointer to the referenced buffer object.
59 /// Returns pointer to the referenced PSO object.
60 /// Deprecated: use GetPipelineResourceSignature() instead.
5961
6062 /// The method calls AddRef() on the returned interface,
6163 /// so Release() must be called to avoid memory leaks.
62 VIRTUAL struct IPipelineState* METHOD(GetPipelineState)(THIS) PURE;
64 // VIRTUAL struct IPipelineState* METHOD(GetPipelineState)(THIS) PURE;
65
66
67 /// Returns pointer to the referenced pipeline resource signature object.
68
69 /// The method calls AddRef() on the returned interface,
70 /// so Release() must be called to avoid memory leaks.
71 VIRTUAL struct IPipelineResourceSignature* METHOD(GetPipelineResourceSignature)(THIS) PURE;
72
6373
6474 /// Binds mutable and dynamice resources using the resource mapping
6575
111121
112122
113123 /// Initializes static resources
124 // Deprecated: use
114125
115126 /// If the parent pipeline state object contain static resources
116127 /// (see Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC), this method must be called
127138 /// no effect and a warning messge will be displayed.
128139 VIRTUAL void METHOD(InitializeStaticResources)(THIS_
129140 const struct IPipelineState* pPipelineState DEFAULT_VALUE(nullptr)) PURE;
141
142 /// AZ TODO: comment
143 VIRTUAL void METHOD(InitializeStaticResourcesWithSignature)(THIS_
144 const struct IPipelineResourceSignature* pResourceSignature DEFAULT_VALUE(nullptr)) PURE;
130145 };
131146 DILIGENT_END_INTERFACE
132147
136151
137152 // clang-format off
138153
139 # define IShaderResourceBinding_GetPipelineState(This) CALL_IFACE_METHOD(ShaderResourceBinding, GetPipelineState, This)
140 # define IShaderResourceBinding_BindResources(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, BindResources, This, __VA_ARGS__)
141 # define IShaderResourceBinding_GetVariableByName(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableByName, This, __VA_ARGS__)
142 # define IShaderResourceBinding_GetVariableCount(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableCount, This, __VA_ARGS__)
143 # define IShaderResourceBinding_GetVariableByIndex(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableByIndex, This, __VA_ARGS__)
144 # define IShaderResourceBinding_InitializeStaticResources(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, InitializeStaticResources, This, __VA_ARGS__)
154 //# define IShaderResourceBinding_GetPipelineState(This) CALL_IFACE_METHOD(ShaderResourceBinding, GetPipelineState, This)
155 # define IShaderResourceBinding_GetPipelineResourceSignature(This) CALL_IFACE_METHOD(ShaderResourceBinding, GetPipelineResourceSignature, This)
156 # define IShaderResourceBinding_BindResources(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, BindResources, This, __VA_ARGS__)
157 # define IShaderResourceBinding_GetVariableByName(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableByName, This, __VA_ARGS__)
158 # define IShaderResourceBinding_GetVariableCount(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableCount, This, __VA_ARGS__)
159 # define IShaderResourceBinding_GetVariableByIndex(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, GetVariableByIndex, This, __VA_ARGS__)
160 # define IShaderResourceBinding_InitializeStaticResources(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, InitializeStaticResources, This, __VA_ARGS__)
161 # define IShaderResourceBinding_InitializeStaticResourcesWithSignature(This, ...) CALL_IFACE_METHOD(ShaderResourceBinding, InitializeStaticResourcesWithSignature, This, __VA_ARGS__)
145162
146163 // clang-format on
147164
1515 include/FramebufferCache.hpp
1616 include/GenerateMipsVkHelper.hpp
1717 include/pch.h
18 include/PipelineLayout.hpp
18 include/PipelineLayoutVk.hpp
19 include/PipelineLayoutCacheVk.hpp
1920 include/PipelineStateVkImpl.hpp
2021 include/QueryManagerVk.hpp
2122 include/QueryVkImpl.hpp
2728 include/ManagedVulkanObject.hpp
2829 include/ShaderResourceBindingVkImpl.hpp
2930 include/ShaderResourceCacheVk.hpp
30 include/ShaderResourceLayoutVk.hpp
3131 include/ShaderVariableVk.hpp
3232 include/SwapChainVkImpl.hpp
3333 include/TextureVkImpl.hpp
3838 include/BottomLevelASVkImpl.hpp
3939 include/TopLevelASVkImpl.hpp
4040 include/ShaderBindingTableVkImpl.hpp
41 include/PipelineResourceSignatureVkImpl.hpp
4142 )
4243
4344 set(VULKAN_UTILS_INCLUDE
9192 src/VulkanDynamicHeap.cpp
9293 src/FramebufferCache.cpp
9394 src/GenerateMipsVkHelper.cpp
94 src/PipelineLayout.cpp
95 src/PipelineLayoutCacheVk.cpp
96 src/PipelineLayoutVk.cpp
9597 src/PipelineStateVkImpl.cpp
9698 src/QueryManagerVk.cpp
9799 src/QueryVkImpl.cpp
102104 src/ShaderVkImpl.cpp
103105 src/ShaderResourceBindingVkImpl.cpp
104106 src/ShaderResourceCacheVk.cpp
105 src/ShaderResourceLayoutVk.cpp
106107 src/ShaderVariableVk.cpp
107108 src/SwapChainVkImpl.cpp
108109 src/TextureVkImpl.cpp
112113 src/BottomLevelASVkImpl.cpp
113114 src/TopLevelASVkImpl.cpp
114115 src/ShaderBindingTableVkImpl.cpp
116 src/PipelineResourceSignatureVkImpl.cpp
115117 )
116118
117119 set(VULKAN_UTILS_SRC
3838 #include "VulkanDynamicHeap.hpp"
3939 #include "ResourceReleaseQueue.hpp"
4040 #include "DescriptorPoolManager.hpp"
41 #include "PipelineLayout.hpp"
41 #include "PipelineLayoutVk.hpp"
4242 #include "GenerateMipsVkHelper.hpp"
4343 #include "BufferVkImpl.hpp"
4444 #include "TextureVkImpl.hpp"
5252 #include "BottomLevelASVkImpl.hpp"
5353 #include "TopLevelASVkImpl.hpp"
5454 #include "ShaderBindingTableVkImpl.hpp"
55 #include "ShaderResourceBindingVkImpl.hpp"
5556
5657
5758 namespace Diligent
395396 void CommitVkVertexBuffers();
396397 void CommitViewports();
397398 void CommitScissorRects();
399 void BindShaderResources(PipelineStateVkImpl* pPipelineStateVk);
398400
399401 __forceinline void TransitionOrVerifyBufferState(BufferVkImpl& Buffer,
400402 RESOURCE_STATE_TRANSITION_MODE TransitionMode,
474476 Uint32 NumCommands = 0;
475477 } m_State;
476478
479
480 /// AZ TODO: comment
481 using DescSetBindingInfoArray = std::array<PipelineLayoutVk::DescriptorSetBindInfo, 3>;
482 DescSetBindingInfoArray m_DescrSetBindInfo;
483
484 /// AZ TODO: comment
485 using ShaderResourcePerPipelineType = std::array<std::array<RefCntAutoPtr<ShaderResourceBindingVkImpl>, MAX_RESOURCE_SIGNATURES>, 3>;
486 ShaderResourcePerPipelineType m_ShaderResources;
477487
478488 /// Render pass that matches currently bound render targets.
479489 /// This render pass may or may not be currently set in the command buffer
530540 VulkanDynamicHeap m_DynamicHeap;
531541 DynamicDescriptorSetAllocator m_DynamicDescrSetAllocator;
532542
533 PipelineLayout::DescriptorSetBindInfo m_DescrSetBindInfo;
534543 std::shared_ptr<GenerateMipsVkHelper> m_GenerateMipsHelper;
535544 RefCntAutoPtr<IShaderResourceBinding> m_GenerateMipsSRB;
536545
+0
-271
Graphics/GraphicsEngineVulkan/include/PipelineLayout.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::PipelineLayout class
31 #include <array>
32
33 #include "ShaderBase.hpp"
34 #include "ShaderResourceLayoutVk.hpp"
35 #include "VulkanUtilities/VulkanObjectWrappers.hpp"
36 #include "VulkanUtilities/VulkanLogicalDevice.hpp"
37 #include "VulkanUtilities/VulkanCommandBuffer.hpp"
38
39 namespace Diligent
40 {
41
42 class RenderDeviceVkImpl;
43 class DeviceContextVkImpl;
44 class ShaderResourceCacheVk;
45
46 /// Implementation of the Diligent::PipelineLayout class
47 class PipelineLayout
48 {
49 public:
50 static VkDescriptorType GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type);
51
52 PipelineLayout();
53 void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask);
54 void Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice);
55
56 VkPipelineLayout GetVkPipelineLayout() const { return m_LayoutMgr.GetVkPipelineLayout(); }
57
58 std::array<Uint32, 2> GetDescriptorSetSizes(Uint32& NumSets) const;
59
60 void InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl,
61 ShaderResourceCacheVk& ResourceCache,
62 IMemoryAllocator& CacheMemAllocator,
63 const char* DbgPipelineName) const;
64
65 void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs,
66 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
67 VkSampler vkImmutableSampler,
68 SHADER_TYPE ShaderType,
69 Uint32& DescriptorSet,
70 Uint32& Binding,
71 Uint32& OffsetInCache);
72
73 Uint32 GetTotalDescriptors(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
74 {
75 VERIFY_EXPR(VarType >= 0 && VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES);
76 return m_LayoutMgr.GetDescriptorSet(VarType).TotalDescriptors;
77 }
78
79 bool IsSameAs(const PipelineLayout& RS) const
80 {
81 return m_LayoutMgr == RS.m_LayoutMgr;
82 }
83 size_t GetHash() const
84 {
85 return m_LayoutMgr.GetHash();
86 }
87
88 VkDescriptorSetLayout GetDynamicDescriptorSetVkLayout() const
89 {
90 return m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC).VkLayout;
91 }
92
93 struct DescriptorSetBindInfo
94 {
95 std::vector<VkDescriptorSet> vkSets;
96 std::vector<uint32_t> DynamicOffsets;
97 const ShaderResourceCacheVk* pResourceCache = nullptr;
98 VkPipelineBindPoint BindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM;
99 Uint32 SetCout = 0;
100 Uint32 DynamicOffsetCount = 0;
101 bool DynamicBuffersPresent = false;
102 bool DynamicDescriptorsBound = false;
103 #ifdef DILIGENT_DEBUG
104 const PipelineLayout* pDbgPipelineLayout = nullptr;
105 #endif
106 DescriptorSetBindInfo() :
107 // clang-format off
108 vkSets (2),
109 DynamicOffsets(64)
110 // clang-format on
111 {
112 }
113
114 void Reset()
115 {
116 pResourceCache = nullptr;
117 BindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM;
118 SetCout = 0;
119 DynamicOffsetCount = 0;
120 DynamicBuffersPresent = false;
121 DynamicDescriptorsBound = false;
122
123 #ifdef DILIGENT_DEBUG
124 // In release mode, do not clear vectors as this causes unnecessary work
125 vkSets.clear();
126 DynamicOffsets.clear();
127
128 pDbgPipelineLayout = nullptr;
129 #endif
130 }
131 };
132
133 // Prepares Vulkan descriptor sets for binding. Actual binding
134 // may not be possible until draw command time because dynamic offsets are
135 // set by the same Vulkan command. If there are no dynamic descriptors, this
136 // function also binds descriptor sets rightaway.
137 void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
138 VkPipelineBindPoint BindPoint,
139 const ShaderResourceCacheVk& ResourceCache,
140 DescriptorSetBindInfo& BindInfo,
141 VkDescriptorSet VkDynamicDescrSet) const;
142
143 // Computes dynamic offsets and binds descriptor sets
144 __forceinline void BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
145 Uint32 CtxId,
146 DeviceContextVkImpl* pCtxVkImpl,
147 DescriptorSetBindInfo& BindInfo) const;
148
149 private:
150 class DescriptorSetLayoutManager
151 {
152 public:
153 struct DescriptorSetLayout
154 {
155 DescriptorSetLayout() noexcept {}
156 // clang-format off
157 DescriptorSetLayout (DescriptorSetLayout&&) = default;
158 DescriptorSetLayout (const DescriptorSetLayout&) = delete;
159 DescriptorSetLayout& operator = (const DescriptorSetLayout&) = delete;
160 DescriptorSetLayout& operator = (DescriptorSetLayout&&) = delete;
161 // clang-format on
162
163 uint32_t TotalDescriptors = 0;
164 int8_t SetIndex = -1;
165 uint8_t NumDynamicDescriptors = 0; // Total number of uniform and storage buffers, counting all array elements
166 uint16_t NumLayoutBindings = 0;
167 VkDescriptorSetLayoutBinding* pBindings = nullptr;
168 VulkanUtilities::DescriptorSetLayoutWrapper VkLayout;
169
170 ~DescriptorSetLayout();
171 void AddBinding(const VkDescriptorSetLayoutBinding& Binding, IMemoryAllocator& MemAllocator);
172 void Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, IMemoryAllocator& MemAllocator, VkDescriptorSetLayoutBinding* pNewBindings);
173 void Release(RenderDeviceVkImpl* pRenderDeviceVk, IMemoryAllocator& MemAllocator, Uint64 CommandQueueMask);
174
175 bool operator==(const DescriptorSetLayout& rhs) const;
176 bool operator!=(const DescriptorSetLayout& rhs) const { return !(*this == rhs); }
177 size_t GetHash() const;
178
179 private:
180 void ReserveMemory(Uint32 NumBindings, IMemoryAllocator& MemAllocator);
181 static size_t GetMemorySize(Uint32 NumBindings);
182 };
183
184 DescriptorSetLayoutManager(IMemoryAllocator& MemAllocator);
185 ~DescriptorSetLayoutManager();
186
187 // clang-format off
188 DescriptorSetLayoutManager (const DescriptorSetLayoutManager&) = delete;
189 DescriptorSetLayoutManager& operator= (const DescriptorSetLayoutManager&) = delete;
190 DescriptorSetLayoutManager (DescriptorSetLayoutManager&&) = delete;
191 DescriptorSetLayoutManager& operator= (DescriptorSetLayoutManager&&) = delete;
192 // clang-format on
193
194 void Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice);
195 void Release(RenderDeviceVkImpl* pRenderDeviceVk, Uint64 CommandQueueMask);
196
197 DescriptorSetLayout& GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE VarType) { return m_DescriptorSetLayouts[VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; }
198 const DescriptorSetLayout& GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE VarType) const { return m_DescriptorSetLayouts[VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; }
199
200 bool operator==(const DescriptorSetLayoutManager& rhs) const;
201 bool operator!=(const DescriptorSetLayoutManager& rhs) const { return !(*this == rhs); }
202 size_t GetHash() const;
203 VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; }
204
205 void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs,
206 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
207 VkSampler vkImmutableSampler,
208 SHADER_TYPE ShaderType,
209 Uint32& DescriptorSet,
210 Uint32& Binding,
211 Uint32& OffsetInCache);
212
213 private:
214 IMemoryAllocator& m_MemAllocator;
215 VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
216 std::array<DescriptorSetLayout, 2> m_DescriptorSetLayouts;
217 std::vector<VkDescriptorSetLayoutBinding, STDAllocatorRawMem<VkDescriptorSetLayoutBinding>> m_LayoutBindings;
218 uint8_t m_ActiveSets = 0;
219 };
220
221 IMemoryAllocator& m_MemAllocator;
222 DescriptorSetLayoutManager m_LayoutMgr;
223 };
224
225
226 __forceinline void PipelineLayout::BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
227 Uint32 CtxId,
228 DeviceContextVkImpl* pCtxVkImpl,
229 DescriptorSetBindInfo& BindInfo) const
230 {
231 VERIFY(BindInfo.pDbgPipelineLayout != nullptr, "Pipeline layout is not initialized, which most likely means that CommitShaderResources() has never been called");
232 VERIFY(BindInfo.pDbgPipelineLayout->IsSameAs(*this), "Inconsistent pipeline layout");
233 VERIFY(BindInfo.DynamicOffsetCount > 0, "This function should only be called for pipelines that contain dynamic descriptors");
234
235 VERIFY_EXPR(BindInfo.pResourceCache != nullptr);
236 #ifdef DILIGENT_DEBUG
237 Uint32 TotalDynamicDescriptors = 0;
238 for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
239 {
240 const auto& Set = m_LayoutMgr.GetDescriptorSet(VarType);
241 TotalDynamicDescriptors += Set.NumDynamicDescriptors;
242 }
243 VERIFY(BindInfo.DynamicOffsetCount == TotalDynamicDescriptors, "Incosistent dynamic buffer size");
244 VERIFY_EXPR(BindInfo.DynamicOffsets.size() >= BindInfo.DynamicOffsetCount);
245 #endif
246
247 auto NumOffsetsWritten = BindInfo.pResourceCache->GetDynamicBufferOffsets(CtxId, pCtxVkImpl, BindInfo.DynamicOffsets);
248 VERIFY_EXPR(NumOffsetsWritten == BindInfo.DynamicOffsetCount);
249 (void)NumOffsetsWritten;
250
251 // Note that there is one global dynamic buffer from which all dynamic resources are suballocated in Vulkan back-end,
252 // and this buffer is not resizable, so the buffer handle can never change.
253
254 // vkCmdBindDescriptorSets causes the sets numbered [firstSet .. firstSet+descriptorSetCount-1] to use the
255 // bindings stored in pDescriptorSets[0 .. descriptorSetCount-1] for subsequent rendering commands
256 // (either compute or graphics, according to the pipelineBindPoint). Any bindings that were previously
257 // applied via these sets are no longer valid (13.2.5)
258 CmdBuffer.BindDescriptorSets(BindInfo.BindPoint,
259 m_LayoutMgr.GetVkPipelineLayout(),
260 0, // First set
261 BindInfo.SetCout,
262 BindInfo.vkSets.data(), // BindInfo.vkSets is never empty
263 // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound (13.2.5)
264 BindInfo.DynamicOffsetCount,
265 BindInfo.DynamicOffsets.data());
266
267 BindInfo.DynamicDescriptorsBound = true;
268 }
269
270 } // namespace Diligent
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::PipelineLayoutCacheVk class
31
32 #include <unordered_set>
33 #include <mutex>
34 #include "VulkanUtilities/VulkanObjectWrappers.hpp"
35 #include "PipelineLayoutVk.hpp"
36
37 namespace Diligent
38 {
39
40 class PipelineLayoutCacheVk
41 {
42 public:
43 PipelineLayoutCacheVk(RenderDeviceVkImpl& DeviceVKImpl) :
44 m_DeviceVk{DeviceVKImpl}
45 {}
46
47 // clang-format off
48 PipelineLayoutCacheVk (const PipelineLayoutCacheVk&) = delete;
49 PipelineLayoutCacheVk (PipelineLayoutCacheVk&&) = delete;
50 PipelineLayoutCacheVk& operator = (const PipelineLayoutCacheVk&) = delete;
51 PipelineLayoutCacheVk& operator = (PipelineLayoutCacheVk&&) = delete;
52 // clang-format on
53
54 ~PipelineLayoutCacheVk();
55
56 RefCntAutoPtr<PipelineLayoutVk> GetLayout(IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount);
57
58 void OnDestroyLayout(PipelineLayoutVk* pLayout);
59
60 private:
61 struct PipelineLayoutHash
62 {
63 std::size_t operator()(const PipelineLayoutVk* Key) const noexcept
64 {
65 return Key->GetHash();
66 }
67 };
68
69 struct PipelineLayoutCompare
70 {
71 bool operator()(const PipelineLayoutVk* lhs, const PipelineLayoutVk* rhs) const noexcept;
72 };
73
74 RenderDeviceVkImpl& m_DeviceVk;
75
76 std::mutex m_Mutex;
77
78 std::unordered_set<PipelineLayoutVk*, PipelineLayoutHash, PipelineLayoutCompare> m_Cache;
79 };
80
81 } // namespace Diligent
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::PipelineLayoutVk class
31 #include <array>
32
33 #include "PipelineResourceSignatureVkImpl.hpp"
34 #include "VulkanUtilities/VulkanObjectWrappers.hpp"
35 #include "VulkanUtilities/VulkanLogicalDevice.hpp"
36 #include "VulkanUtilities/VulkanCommandBuffer.hpp"
37
38 namespace Diligent
39 {
40
41 class DeviceContextVkImpl;
42 class ShaderResourceCacheVk;
43
44 /// Implementation of the Diligent::PipelineLayoutVk class
45 class PipelineLayoutVk final : public ObjectBase<IObject>
46 {
47 public:
48 PipelineLayoutVk(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount);
49 ~PipelineLayoutVk();
50
51 using ObjectBase<IObject>::Release;
52
53 void Finalize();
54
55 size_t GetHash() const;
56
57 VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; }
58 PIPELINE_TYPE GetPipelineType() const { return m_PipelineType; }
59 Uint32 GetSignatureCount() const { return m_SignatureCount; }
60 Uint32 GetDescriptorSetCount() const { return m_DescrSetCount; }
61 Uint32 GetDynamicOffsetCount() const { return m_DynamicOffsetCount; }
62
63 IPipelineResourceSignature* GetSignature(Uint32 index) const
64 {
65 VERIFY_EXPR(index < m_SignatureCount);
66 return m_Signatures[index].RawPtr<IPipelineResourceSignature>();
67 }
68
69 bool HasSignature(IPipelineResourceSignature* pPRS) const
70 {
71 Uint32 Index = pPRS->GetDesc().BindingIndex;
72 return Index < m_SignatureCount && m_Signatures[Index].RawPtr() == pPRS;
73 }
74
75 Uint32 GetDescrSetIndex(IPipelineResourceSignature* pPRS) const
76 {
77 Uint32 Index = pPRS->GetDesc().BindingIndex;
78 return Index < m_SignatureCount ? m_DescSetOffset[Index] : ~0u;
79 }
80
81 Uint32 GetDynamicBufferOffset(IPipelineResourceSignature* pPRS) const
82 {
83 Uint32 Index = pPRS->GetDesc().BindingIndex;
84 return Index < m_SignatureCount ? m_DynBufOffset[Index] : 0;
85 }
86
87 struct ResourceInfo
88 {
89 SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN;
90 Uint16 DescrSetIndex = 0;
91 Uint16 BindingIndex = 0;
92 };
93 bool GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const;
94
95 using DescriptorSetBindInfo = PipelineResourceSignatureVkImpl::DescriptorSetBindInfo;
96
97 // Computes dynamic offsets and binds descriptor sets
98 __forceinline void BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
99 Uint32 CtxId,
100 DeviceContextVkImpl* pCtxVkImpl,
101 DescriptorSetBindInfo& BindInfo) const;
102
103 private:
104 VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
105
106 RenderDeviceVkImpl* m_pDeviceVk;
107
108 // AZ TODO: pack bits
109 Uint16 m_DynamicOffsetCount = 0;
110 Uint8 m_SignatureCount = 0;
111 Uint8 m_DescrSetCount = 0;
112
113 PIPELINE_TYPE m_PipelineType = PIPELINE_TYPE(0xFF);
114
115 using SignatureArray = std::array<RefCntAutoPtr<PipelineResourceSignatureVkImpl>, MAX_RESOURCE_SIGNATURES>;
116 using DescSetOffsetArray = std::array<Uint8, MAX_RESOURCE_SIGNATURES>;
117 using DynBufOffsetArray = std::array<Uint16, MAX_RESOURCE_SIGNATURES>;
118
119 SignatureArray m_Signatures;
120 DescSetOffsetArray m_DescSetOffset = {};
121 DynBufOffsetArray m_DynBufOffset = {};
122 };
123
124
125 __forceinline void PipelineLayoutVk::BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
126 Uint32 CtxId,
127 DeviceContextVkImpl* pCtxVkImpl,
128 DescriptorSetBindInfo& BindInfo) const
129 {
130 /*
131 VERIFY(BindInfo.pDbgPipelineLayout != nullptr, "Pipeline layout is not initialized, which most likely means that CommitShaderResources() has never been called");
132 VERIFY(BindInfo.pDbgPipelineLayout->IsSameAs(*this), "Inconsistent pipeline layout");
133 VERIFY(BindInfo.DynamicOffsetCount > 0, "This function should only be called for pipelines that contain dynamic descriptors");
134 VERIFY_EXPR(BindInfo.pResourceCache != nullptr);
135
136 #ifdef DILIGENT_DEBUG
137 Uint32 TotalDynamicDescriptors = 0;
138 for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
139 VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
140 VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
141 {
142 const auto& Set = m_LayoutMgr.GetDescriptorSet(VarType);
143 TotalDynamicDescriptors += Set.NumDynamicDescriptors;
144 }
145 VERIFY(BindInfo.DynamicOffsetCount == TotalDynamicDescriptors, "Incosistent dynamic buffer size");
146 VERIFY_EXPR(BindInfo.DynamicOffsets.size() >= BindInfo.DynamicOffsetCount);
147 #endif
148
149 auto NumOffsetsWritten = BindInfo.pResourceCache->GetDynamicBufferOffsets(CtxId, pCtxVkImpl, BindInfo.DynamicOffsets);
150 VERIFY_EXPR(NumOffsetsWritten == BindInfo.DynamicOffsetCount);
151 (void)NumOffsetsWritten;
152
153 // Note that there is one global dynamic buffer from which all dynamic resources are suballocated in Vulkan back-end,
154 // and this buffer is not resizable, so the buffer handle can never change.
155
156 // vkCmdBindDescriptorSets causes the sets numbered [firstSet .. firstSet+descriptorSetCount-1] to use the
157 // bindings stored in pDescriptorSets[0 .. descriptorSetCount-1] for subsequent rendering commands
158 // (either compute or graphics, according to the pipelineBindPoint). Any bindings that were previously
159 // applied via these sets are no longer valid (13.2.5)
160 CmdBuffer.BindDescriptorSets(BindInfo.BindPoint,
161 m_LayoutMgr.GetVkPipelineLayout(),
162 0, // First set
163 BindInfo.SetCout,
164 BindInfo.vkSets.data(), // BindInfo.vkSets is never empty
165 // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound (13.2.5)
166 BindInfo.DynamicOffsetCount,
167 BindInfo.DynamicOffsets.data());
168
169 BindInfo.DynamicDescriptorsBound = true;
170 */
171 }
172
173 } // namespace Diligent
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::PipelineResourceSignatureVkImpl class
31 #include <array>
32
33 #include "PipelineResourceSignatureBase.hpp"
34 #include "VulkanUtilities/VulkanObjectWrappers.hpp"
35 #include "VulkanUtilities/VulkanLogicalDevice.hpp"
36 #include "VulkanUtilities/VulkanCommandBuffer.hpp"
37 #include "SRBMemoryAllocator.hpp"
38
39 namespace Diligent
40 {
41 class RenderDeviceVkImpl;
42 class ShaderResourceCacheVk;
43 class ShaderVariableManagerVk;
44 class DeviceContextVkImpl;
45
46 /// Implementation of the Diligent::PipelineResourceSignatureVkImpl class
47 class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceVkImpl>
48 {
49 public:
50 using TPipelineResourceSignatureBase = PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceVkImpl>;
51
52 PipelineResourceSignatureVkImpl(IReferenceCounters* pRefCounters,
53 RenderDeviceVkImpl* pDevice,
54 const PipelineResourceSignatureDesc& Desc,
55 bool bIsDeviceInternal = false);
56 ~PipelineResourceSignatureVkImpl();
57
58 Uint32 GetDynamicBufferCount() const { return m_DynamicBufferCount; }
59 Uint8 GetNumShaderStages() const { return m_NumShaders; }
60 Uint32 GetTotalResourceCount() const { return m_Desc.NumResources; }
61
62 static constexpr Uint8 InvalidSamplerInd = 0xFF;
63
64 struct PackedBindingIndex
65 {
66 Uint16 Binding;
67 Uint8 DescSet : 1; // 0 - static, 1 - dynamic
68 Uint8 SamplerInd = InvalidSamplerInd;
69 };
70
71 const PackedBindingIndex& GetBinding(Uint32 ResIndex) const
72 {
73 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
74 return m_pBindingIndices[ResIndex];
75 }
76
77 const PipelineResourceDesc& GetResource(Uint32 ResIndex) const
78 {
79 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
80 return m_Desc.Resources[ResIndex];
81 }
82
83 VkDescriptorSetLayout GetStaticVkDescriptorSetLayout() const { return m_VkDescSetLayouts[0]; }
84 VkDescriptorSetLayout GetDynamicVkDescriptorSetLayout() const { return m_VkDescSetLayouts[1]; }
85
86 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
87 bool InitStaticResources) override final;
88
89 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
90
91 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
92
93 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
94
95 using VkDescSetArray = std::array<VkDescriptorSet, MAX_RESOURCE_SIGNATURES * 2>;
96
97 struct DescriptorSetBindInfo
98 {
99 VkDescSetArray vkSets;
100 std::vector<uint32_t> DynamicOffsets;
101 const ShaderResourceCacheVk* pResourceCache = nullptr;
102 Uint32 SetCout = 0;
103 Uint32 DynamicOffsetCount = 0;
104 bool DynamicBuffersPresent = false;
105 bool DynamicDescriptorsBound = false;
106 #ifdef DILIGENT_DEBUG
107 //const PipelineLayoutVk* pDbgPipelineLayout = nullptr;
108 #endif
109 DescriptorSetBindInfo() :
110 DynamicOffsets(64)
111 {
112 }
113
114 void Reset()
115 {
116 pResourceCache = nullptr;
117 SetCout = 0;
118 DynamicOffsetCount = 0;
119 DynamicBuffersPresent = false;
120 DynamicDescriptorsBound = false;
121
122 #ifdef DILIGENT_DEBUG
123 // In release mode, do not clear vectors as this causes unnecessary work
124 DynamicOffsets.clear();
125
126 //pDbgPipelineLayout = nullptr;
127 #endif
128 }
129 };
130
131 void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
132 VkPipelineBindPoint BindPoint,
133 const ShaderResourceCacheVk& ResourceCache,
134 DescriptorSetBindInfo& BindInfo,
135 VkDescriptorSet VkDynamicDescrSet) const;
136
137 static VkDescriptorType GetVkDescriptorType(const PipelineResourceDesc& Res);
138
139 SHADER_TYPE GetShaderStageType(Uint32 StageIndex) const;
140
141 SRBMemoryAllocator& GetSRBMemoryAllocator()
142 {
143 return m_SRBMemAllocator;
144 }
145
146 void InitResourceCache(ShaderResourceCacheVk& ResourceCache,
147 IMemoryAllocator& CacheMemAllocator,
148 const char* DbgPipelineName) const;
149
150 // Initializes resource slots in the ResourceCache
151 void InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache) const;
152
153 void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const;
154
155 private:
156 void Destruct();
157
158 VulkanUtilities::DescriptorSetLayoutWrapper m_VkDescSetLayouts[2];
159
160 PackedBindingIndex* m_pBindingIndices = nullptr; // [m_Desc.NumResources]
161
162 SHADER_TYPE m_ShaderStages = SHADER_TYPE_UNKNOWN;
163
164 Uint16 m_DynamicBufferCount = 0;
165 Uint8 m_NumShaders = 0;
166
167 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_StaticVarIndex = {-1, -1, -1, -1, -1, -1};
168 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
169
170 ShaderResourceCacheVk* m_pResourceCache = nullptr;
171 ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; // [0..MAX_SHADERS_IN_PIPELINE]
172
173 SRBMemoryAllocator m_SRBMemAllocator;
174 };
175
176
177 } // namespace Diligent
3434 #include "RenderDeviceVk.h"
3535 #include "PipelineStateVk.h"
3636 #include "PipelineStateBase.hpp"
37 #include "PipelineLayout.hpp"
38 #include "ShaderResourceLayoutVk.hpp"
3937 #include "ShaderVariableVk.hpp"
4038 #include "FixedBlockMemoryAllocator.hpp"
4139 #include "SRBMemoryAllocator.hpp"
4240 #include "VulkanUtilities/VulkanObjectWrappers.hpp"
4341 #include "VulkanUtilities/VulkanCommandBuffer.hpp"
44 #include "PipelineLayout.hpp"
4542 #include "RenderDeviceVkImpl.hpp"
43 #include "PipelineLayoutVk.hpp"
4644
4745 namespace Diligent
4846 {
4947
5048 class FixedBlockMemoryAllocator;
5149 class ShaderVariableManagerVk;
50 class ShaderVkImpl;
5251
5352 /// Pipeline state object implementation in Vulkan backend.
5453 class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl>
6362
6463 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineStateVk, TPipelineStateBase)
6564
66 /// Implementation of IPipelineState::CreateShaderResourceBinding() in Vulkan backend.
67 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final;
68
6965 /// Implementation of IPipelineState::IsCompatibleWith() in Vulkan backend.
7066 virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
7167
7874 /// Implementation of IPipelineState::BindStaticResources() in Vulkan backend.
7975 virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final;
8076
81 /// Implementation of IPipelineState::GetStaticVariableCount() in Vulkan backend.
82 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
77 /// Implementation of IPipelineState::GetResourceSignatureCount() in Vulkan backend.
78 virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_PipelineLayout->GetSignatureCount(); }
8379
84 /// Implementation of IPipelineState::GetStaticVariableByName() in Vulkan backend.
85 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
80 /// Implementation of IPipelineState::GetResourceSignature() in Vulkan backend.
81 virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final { return m_PipelineLayout->GetSignature(Index); }
8682
87 /// Implementation of IPipelineState::GetStaticVariableByIndex() in Vulkan backend.
88 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
89
90 void CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding,
91 DeviceContextVkImpl* pCtxVkImpl,
92 bool CommitResources,
93 RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
94 PipelineLayout::DescriptorSetBindInfo* pDescrSetBindInfo) const;
95
96 __forceinline void BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
97 Uint32 CtxId,
98 DeviceContextVkImpl* pCtxVkImpl,
99 PipelineLayout::DescriptorSetBindInfo& BindInfo)
83 __forceinline void BindDescriptorSetsWithDynamicOffsets(VulkanUtilities::VulkanCommandBuffer& CmdBuffer,
84 Uint32 CtxId,
85 DeviceContextVkImpl* pCtxVkImpl,
86 PipelineLayoutVk::DescriptorSetBindInfo& BindInfo)
10087 {
101 m_PipelineLayout.BindDescriptorSetsWithDynamicOffsets(CmdBuffer, CtxId, pCtxVkImpl, BindInfo);
88 m_PipelineLayout->BindDescriptorSetsWithDynamicOffsets(CmdBuffer, CtxId, pCtxVkImpl, BindInfo);
10289 }
10390
104 const PipelineLayout& GetPipelineLayout() const { return m_PipelineLayout; }
105
106 const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const
107 {
108 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
109 return m_ShaderResourceLayouts[ShaderInd];
110 }
111
112 SRBMemoryAllocator& GetSRBMemoryAllocator()
113 {
114 return m_SRBMemAllocator;
115 }
91 const PipelineLayoutVk& GetPipelineLayout() const { return *m_PipelineLayout; }
11692
11793 static RenderPassDesc GetImplicitRenderPassDesc(Uint32 NumRenderTargets,
11894 const TEXTURE_FORMAT RTVFormats[],
125101
126102 void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const;
127103
104 bool IsIncompatibleWith(IPipelineResourceSignature* pPRS) const
105 {
106 return !m_PipelineLayout->HasSignature(pPRS);
107 }
108
109 struct ShaderStageInfo
110 {
111 ShaderStageInfo() {}
112 ShaderStageInfo(const ShaderVkImpl* pShader);
113
114 void Append(const ShaderVkImpl* pShader);
115 size_t Count() const;
116
117 // Shader stage type. All shaders in the stage must have the same type.
118 SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
119
120 std::vector<const ShaderVkImpl*> Shaders;
121 std::vector<std::vector<uint32_t>> SPIRVs;
122 };
123 using TShaderStages = std::vector<ShaderStageInfo>;
124
128125 private:
129 using TShaderStages = ShaderResourceLayoutVk::TShaderStages;
130
131126 template <typename PSOCreateInfoType>
132127 TShaderStages InitInternalObjects(const PSOCreateInfoType& CreateInfo,
133128 std::vector<VkPipelineShaderStageCreateInfo>& vkShaderStages,
134129 std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules);
130
131 void InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
132 TShaderStages& ShaderStages);
135133
136134 void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
137135 TShaderStages& ShaderStages);
138136
139137 void Destruct();
140138
141 const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const
142 {
143 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
144 return m_ShaderResourceLayouts[GetNumShaderStages() + ShaderInd];
145 }
146
147 const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const
148 {
149 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
150 return m_StaticResCaches[ShaderInd];
151 }
152
153 const ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
154 {
155 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
156 return m_StaticVarsMgrs[ShaderInd];
157 }
158
159 ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; // [m_NumShaderStages * 2]
160 ShaderResourceCacheVk* m_StaticResCaches = nullptr; // [m_NumShaderStages]
161 ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; // [m_NumShaderStages]
162
163 SRBMemoryAllocator m_SRBMemAllocator;
139 void* m_pRawMem = nullptr; // AZ TODO: remove
164140
165141 VulkanUtilities::PipelineWrapper m_Pipeline;
166 PipelineLayout m_PipelineLayout;
167
168 // Resource layout index in m_ShaderResourceLayouts array for every shader stage,
169 // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
170 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
171 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
142 RefCntAutoPtr<PipelineLayoutVk> m_PipelineLayout;
172143
173144 bool m_HasStaticResources = false;
174145 bool m_HasNonStaticResources = false;
4646 #include "VulkanUploadHeap.hpp"
4747 #include "FramebufferCache.hpp"
4848 #include "RenderPassCache.hpp"
49 #include "PipelineLayoutCacheVk.hpp"
4950 #include "CommandPoolManager.hpp"
5051 #include "DXCompiler.hpp"
5152
129130 virtual void DILIGENT_CALL_TYPE CreateSBT(const ShaderBindingTableDesc& Desc,
130131 IShaderBindingTable** ppSBT) override final;
131132
133 /// Implementation of IRenderDevice::CreatePipelineResourceSignature() in Vulkan backend.
134 virtual void DILIGENT_CALL_TYPE CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc,
135 IPipelineResourceSignature** ppSignature) override final;
136
132137 /// Implementation of IRenderDeviceVk::GetVkDevice().
133138 virtual VkDevice DILIGENT_CALL_TYPE GetVkDevice() override final { return m_LogicalVkDevice->GetVkDevice(); }
134139
188193
189194 FramebufferCache& GetFramebufferCache() { return m_FramebufferCache; }
190195 RenderPassCache& GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache; }
196
197 PipelineLayoutCacheVk& GetPipelineLayoutCache() { return m_PipelineLayoutCache; }
191198
192199 VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties, VkMemoryAllocateFlags AllocateFlags = 0)
193200 {
223230 return m_Properties;
224231 }
225232
233 void CreatePipelineLayout(IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount, PipelineLayoutVk** ppPipelineLayout);
234
226235 private:
227236 template <typename PSOCreateInfoType>
228237 void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
243252 EngineVkCreateInfo m_EngineAttribs;
244253
245254 FramebufferCache m_FramebufferCache;
255 PipelineLayoutCacheVk m_PipelineLayoutCache;
246256 RenderPassCache m_ImplicitRenderPassCache;
247257 DescriptorSetAllocator m_DescriptorSetAllocator;
248258 DescriptorPoolManager m_DynamicDescriptorPool;
259269 std::unique_ptr<IDXCompiler> m_pDxCompiler;
260270
261271 Properties m_Properties;
272
273 FixedBlockMemoryAllocator m_PipelineLayoutAllocator;
262274 };
263275
264276 } // namespace Diligent
3535 #include "ShaderBase.hpp"
3636 #include "ShaderResourceCacheVk.hpp"
3737 #include "ShaderVariableVk.hpp"
38 #include "PipelineResourceSignatureVkImpl.hpp"
3839
3940 namespace Diligent
4041 {
4142
42 class PipelineStateVkImpl;
43 class PipelineResourceSignatureVkImpl;
4344
4445 /// Implementation of the Diligent::IShaderResourceBindingVk interface
4546 // sizeof(ShaderResourceBindingVkImpl) == 72 (x64, msvc, Release)
46 class ShaderResourceBindingVkImpl final : public ShaderResourceBindingBase<IShaderResourceBindingVk, PipelineStateVkImpl>
47 class ShaderResourceBindingVkImpl final : public ShaderResourceBindingBase<IShaderResourceBindingVk, PipelineResourceSignatureVkImpl>
4748 {
4849 public:
49 using TBase = ShaderResourceBindingBase<IShaderResourceBindingVk, PipelineStateVkImpl>;
50 using TBase = ShaderResourceBindingBase<IShaderResourceBindingVk, PipelineResourceSignatureVkImpl>;
5051
51 ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters,
52 PipelineStateVkImpl* pPSO,
53 bool IsPSOInternal);
52 ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters,
53 PipelineResourceSignatureVkImpl* pPRS,
54 bool IsPSOInternal);
5455 ~ShaderResourceBindingVkImpl();
5556
5657 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBindingVk, TBase)
7071 /// Implementation of IShaderResourceBinding::InitializeStaticResources() in Vulkan backend.
7172 virtual void DILIGENT_CALL_TYPE InitializeStaticResources(const IPipelineState* pPipelineState) override final;
7273
74 /// Implementation of IShaderResourceBinding::InitializeStaticResourcesWithSignature() in Vulkan backend.
75 virtual void DILIGENT_CALL_TYPE InitializeStaticResourcesWithSignature(const IPipelineResourceSignature* pResourceSignature) override final;
76
7377 ShaderResourceCacheVk& GetResourceCache() { return m_ShaderResourceCache; }
7478
7579 bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; }
7781 private:
7882 void Destruct();
7983
84 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ShaderVarIndex = {-1, -1, -1, -1, -1, -1};
85 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
86
8087 ShaderResourceCacheVk m_ShaderResourceCache;
8188 ShaderVariableManagerVk* m_pShaderVarMgrs = nullptr;
82
83 // Resource layout index in m_ShaderResourceCache array for every shader stage,
84 // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
85 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
86 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
8789
8890 bool m_bStaticResourcesInitialized = false;
8991 Uint8 m_NumShaders = 0;
8989
9090 ~ShaderResourceCacheVk();
9191
92 static size_t GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[]);
93
94 void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, Uint32 SetSizes[]);
95 void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type);
92 static size_t GetRequiredMemorySize(Uint32 NumSets, const Uint32* SetSizes);
93
94 void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, const Uint32* SetSizes);
95 void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, VkDescriptorType Type);
9696
9797 // sizeof(Resource) == 16 (x64, msvc, Release)
9898 struct Resource
9999 {
100100 // clang-format off
101 explicit Resource(SPIRVShaderResourceAttribs::ResourceType _Type) noexcept :
101 explicit Resource(VkDescriptorType _Type) noexcept :
102102 Type{_Type}
103103 {}
104104
107107 Resource& operator = (const Resource&) = delete;
108108 Resource& operator = (Resource&&) = delete;
109109
110 /* 0 */ const SPIRVShaderResourceAttribs::ResourceType Type;
111 /*1-7*/ // Unused
112 /* 8 */ RefCntAutoPtr<IDeviceObject> pObject;
110 /* 0 */ const VkDescriptorType Type;
111 /*4-7*/ // Unused
112 /* 8 */ RefCntAutoPtr<IDeviceObject> pObject;
113113
114114 VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const;
115115 VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const;
212212 IMemoryAllocator* m_pAllocator = nullptr;
213213 void* m_pMemory = nullptr;
214214 Uint16 m_NumSets = 0;
215 // Total number of dynamic buffers bound in the resource cache regardless of the variable type
215
216 // Total number of dynamic buffers bound in the resource cache regardless of the variable type.
217 // This variable is not equal to dynamic offsets count, it just a indicator that dynamic descriptor has dynamic buffers.
216218 Uint16 m_NumDynamicBuffers = 0;
217219 Uint32 m_TotalResources = 0;
218220
242244 {
243245 const auto& DescrSet = GetDescriptorSet(set);
244246 Uint32 res = 0;
247
248 // AZ TODO: optimize
245249 while (res < DescrSet.GetSize())
246250 {
247251 const auto& Res = DescrSet.GetResource(res);
248 if (Res.Type != SPIRVShaderResourceAttribs::ResourceType::UniformBuffer)
249 break;
250
251 const auto* pBufferVk = Res.pObject.RawPtr<const BufferVkImpl>();
252 auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
253 Offsets[OffsetInd++] = Offset;
254
252
253 if (Res.Type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
254 {
255 const auto* pBufferVk = Res.pObject.RawPtr<const BufferVkImpl>();
256 auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
257 Offsets[OffsetInd++] = Offset;
258 }
259 if (Res.Type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
260 {
261 const auto* pBufferVkView = Res.pObject.RawPtr<const BufferViewVkImpl>();
262 const auto* pBufferVk = pBufferVkView != nullptr ? pBufferVkView->GetBufferVk() : 0;
263 auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
264 Offsets[OffsetInd++] = Offset;
265 }
255266 ++res;
256267 }
257
258 while (res < DescrSet.GetSize())
259 {
260 const auto& Res = DescrSet.GetResource(res);
261 if (Res.Type != SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer &&
262 Res.Type != SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer)
263 break;
264
265 const auto* pBufferVkView = Res.pObject.RawPtr<const BufferViewVkImpl>();
266 const auto* pBufferVk = pBufferVkView != nullptr ? pBufferVkView->GetBufferVk() : 0;
267 auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
268 Offsets[OffsetInd++] = Offset;
269
270 ++res;
271 }
272
273 #ifdef DILIGENT_DEBUG
274 for (; res < DescrSet.GetSize(); ++res)
275 {
276 const auto& Res = DescrSet.GetResource(res);
277 // clang-format off
278 VERIFY(Res.Type != SPIRVShaderResourceAttribs::ResourceType::UniformBuffer &&
279 Res.Type != SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer &&
280 Res.Type != SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer,
281 "All uniform and storage buffers are expected to go first in the beginning of each descriptor set");
282 // clang-format on
283 }
284 #endif
285268 }
286269 return OffsetInd;
287270 }
+0
-478
Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.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::ShaderResourceLayoutVk class
31
32 // All resources are stored in a single continuous chunk of memory using the following layout:
33 //
34 // m_ResourceBuffer
35 // |
36 // || VkResource[0] ... VkResource[s-1] | VkResource[s] ... VkResource[s+m-1] | VkResource[s+m] ... VkResource[s+m+d-1] || ||
37 // || | | || ||
38 // || VARIABLE_TYPE_STATIC | VARIABLE_TYPE_MUTABLE | VARIABLE_TYPE_DYNAMIC || Immutable Samplers ||
39 // || | | || ||
40 //
41 // s == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC]
42 // m == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE]
43 // d == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC]
44 //
45 //
46 // Every ShaderVariableVkImpl variable managed by ShaderVariableManagerVk keeps a reference to corresponding VkResource.
47 //
48 // ___________________________ ___________________________________________________________________________
49 // | | unique_ptr | | | | |
50 // | ShaderResourceLayoutVk |--------------->| VkResource[0] | VkResource[1] | ... | VkResource[s+m+d-1] |
51 // |___________________________| |___________________|_________________|_______________|_____________________|
52 // A A
53 // / |
54 // Ref Ref
55 // / |
56 // __________________________ __________________/___________________________|___________________________
57 // | | | | | |
58 // | ShaderVariableManagerVk |---------------->| ShaderVariableVkImpl[0] | ShaderVariableVkImpl[1] | ... |
59 // |__________________________| |___________________________|____________________________|_________________|
60 //
61 //
62 //
63 //
64 // Resources in the resource cache are identified by the descriptor set index and the offset from the set start
65 //
66 // ___________________________ ___________________________________________________________________________
67 // | | unique_ptr | | | | |
68 // | ShaderResourceLayoutVk |--------------->| VkResource[0] | VkResource[1] | ... | VkResource[s+m+d-1] |
69 // |___________________________| |___________________|_________________|_______________|_____________________|
70 // | |
71 // | |
72 // | (DescriptorSet, CacheOffset) / (DescriptorSet, CacheOffset)
73 // \ /
74 // __________________________ ________V_______________________________________________________V_______
75 // | | | |
76 // | ShaderResourceCacheVk |---------------->| Resources |
77 // |__________________________| |________________________________________________________________________|
78 //
79 //
80 //
81 // Every pipeline state object (PipelineStateVkImpl) keeps the following layouts:
82 // * One layout object per shader stage to facilitate management of static shader resources
83 // - Uses artificial layout where resource binding matches the resource type (SPIRVShaderResourceAttribs::ResourceType)
84 // * One layout object per shader stage used by SRBs to manage all resource types:
85 // - All variable types are preserved
86 // - Bindings, descriptor sets and offsets are assigned during the initialization
87
88 #include <array>
89 #include <memory>
90 #include <unordered_map>
91
92 #include "PipelineState.h"
93 #include "ShaderBase.hpp"
94 #include "HashUtils.hpp"
95 #include "ShaderResourceCacheVk.hpp"
96 #include "VulkanUtilities/VulkanLogicalDevice.hpp"
97 #include "StringPool.hpp"
98
99 namespace Diligent
100 {
101
102 class ShaderVkImpl;
103
104 /// Diligent::ShaderResourceLayoutVk class
105 // sizeof(ShaderResourceLayoutVk)==40 (MS compiler, x64)
106 class ShaderResourceLayoutVk
107 {
108 public:
109 struct ShaderStageInfo
110 {
111 ShaderStageInfo() {}
112 ShaderStageInfo(const ShaderVkImpl* pShader);
113
114 void Append(const ShaderVkImpl* pShader);
115 size_t Count() const;
116
117 // Shader stage type. All shaders in the stage must have the same type.
118 SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
119
120 std::vector<const ShaderVkImpl*> Shaders;
121 std::vector<std::vector<uint32_t>> SPIRVs;
122 };
123 using TShaderStages = std::vector<ShaderStageInfo>;
124
125 ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept :
126 m_LogicalDevice{LogicalDevice}
127 {
128 #if defined(_MSC_VER) && defined(_WIN64)
129 static_assert(sizeof(*this) == 40, "Unexpected sizeof(ShaderResourceLayoutVk).");
130 #endif
131 }
132
133 // clang-format off
134 ShaderResourceLayoutVk (const ShaderResourceLayoutVk&) = delete;
135 ShaderResourceLayoutVk (ShaderResourceLayoutVk&&) = delete;
136 ShaderResourceLayoutVk& operator = (const ShaderResourceLayoutVk&) = delete;
137 ShaderResourceLayoutVk& operator = (ShaderResourceLayoutVk&&) = delete;
138 // clang-format on
139
140 ~ShaderResourceLayoutVk();
141
142 // This method is called by PipelineStateVkImpl class instance to initialize static
143 // shader resource layout and the cache
144 void InitializeStaticResourceLayout(const std::vector<const ShaderVkImpl*>& Shaders,
145 IMemoryAllocator& LayoutDataAllocator,
146 const PipelineResourceLayoutDesc& ResourceLayoutDesc,
147 ShaderResourceCacheVk& StaticResourceCache);
148
149 // This method is called by PipelineStateVkImpl class instance to initialize resource
150 // layouts for all shader stages in the pipeline.
151 static void Initialize(IRenderDevice* pRenderDevice,
152 TShaderStages& ShaderStages,
153 ShaderResourceLayoutVk Layouts[],
154 IMemoryAllocator& LayoutDataAllocator,
155 const PipelineResourceLayoutDesc& ResourceLayoutDesc,
156 class PipelineLayout& PipelineLayout,
157 bool VerifyVariables,
158 bool VerifyImmutableSamplers);
159
160 // sizeof(VkResource) == 32 (x64)
161 struct VkResource
162 {
163 // clang-format off
164 VkResource (const VkResource&) = delete;
165 VkResource ( VkResource&&) = delete;
166 VkResource& operator = (const VkResource&) = delete;
167 VkResource& operator = ( VkResource&&) = delete;
168
169 static constexpr const Uint32 CacheOffsetBits = 21;
170 static constexpr const Uint32 SamplerIndBits = 8;
171 static constexpr const Uint32 VariableTypeBits = 2;
172 static constexpr const Uint32 ImmutableSamplerFlagBits = 1;
173 static_assert(CacheOffsetBits + SamplerIndBits + VariableTypeBits + ImmutableSamplerFlagBits == 32, "Elements are expected to be packed into 32 bits");
174 static_assert(SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES <= (1<<VariableTypeBits), "Not enough bits to represent SHADER_RESOURCE_VARIABLE_TYPE");
175
176 static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1;
177
178 static constexpr const Uint32 ResourceDimBits = 7;
179 static constexpr const Uint32 IsMSFlagBits = 8 - ResourceDimBits;
180 static_assert(RESOURCE_DIM_NUM_DIMENSIONS <= (1 << ResourceDimBits), "Not enough bits to represent RESOURCE_DIMENSION");
181
182 using ResourceType = SPIRVShaderResourceAttribs::ResourceType;
183
184 /* 0 */ const Uint16 Binding;
185 /* 2 */ const Uint16 DescriptorSet;
186
187 /* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set
188 /* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler
189 // assigned to separate image
190 /* 7.5 */ const Uint32 VariableType : VariableTypeBits;
191 /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits;
192
193 /* 8 */ const Uint16 ArraySize;
194
195 /* 10 */ const ResourceType Type;
196 /* 11.0*/ const Uint8 ResourceDim : ResourceDimBits;
197 /* 11.7*/ const Uint8 IsMS : IsMSFlagBits;
198
199 /* 16 */ const char* const Name;
200 /* 24 */ const ShaderResourceLayoutVk& ParentResLayout;
201
202 #ifdef DILIGENT_DEVELOPMENT
203 /* 32 */ const Uint32 BufferStaticSize;
204 /* 36 */ const Uint32 BufferStride;
205 #endif
206 // clang-format on
207
208 VkResource(const ShaderResourceLayoutVk& _ParentLayout,
209 const char* _Name,
210 const SPIRVShaderResourceAttribs& _Attribs,
211 SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
212 uint32_t _Binding,
213 uint32_t _DescriptorSet,
214 Uint32 _CacheOffset,
215 Uint32 _SamplerInd,
216 bool _ImmutableSamplerAssigned) noexcept :
217 // clang-format off
218 Binding {static_cast<decltype(Binding)>(_Binding) },
219 DescriptorSet {static_cast<decltype(DescriptorSet)>(_DescriptorSet)},
220 CacheOffset {_CacheOffset },
221 SamplerInd {_SamplerInd },
222 VariableType {_VariableType},
223 ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U},
224 ArraySize {_Attribs.ArraySize },
225 Type {_Attribs.Type },
226 ResourceDim {_Attribs.ResourceDim},
227 IsMS {_Attribs.IsMS },
228 #ifdef DILIGENT_DEVELOPMENT
229 BufferStaticSize {_Attribs.BufferStaticSize},
230 BufferStride {_Attribs.BufferStride },
231 #endif
232 Name {_Name },
233 ParentResLayout {_ParentLayout}
234 // clang-format on
235 {
236 #if defined(_MSC_VER) && defined(_WIN64) && !defined(DILIGENT_DEVELOPMENT)
237 static_assert(sizeof(*this) == 32, "Unexpected sizeof(VkResource)");
238 #endif
239 // clang-format off
240 VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) );
241 VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) );
242 VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max() );
243 VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits<decltype(DescriptorSet)>::max());
244 VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type (", Uint32{_VariableType}, ") exceeds max representable value ", (1 << VariableTypeBits) );
245 VERIFY(_Attribs.ResourceDim < (1 << ResourceDimBits), "Resource dimension (", Uint32{_Attribs.ResourceDim}, ") exceeds max representable value ", (1 << ResourceDimBits) );
246 // clang-format on
247 }
248
249
250 // Checks if a resource is bound in ResourceCache at the given ArrayIndex
251 bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const;
252
253 // Binds a resource pObject in the ResourceCache
254 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const;
255
256 // Updates resource descriptor in the descriptor set
257 inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
258 uint32_t ArrayElement,
259 const VkDescriptorImageInfo* pImageInfo,
260 const VkDescriptorBufferInfo* pBufferInfo,
261 const VkBufferView* pTexelBufferView,
262 const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const;
263
264 bool IsImmutableSamplerAssigned() const
265 {
266 VERIFY(ImmutableSamplerAssigned == 0 ||
267 Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
268 Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler,
269 "Immutable sampler can only be assigned to a sampled image or separate sampler");
270 return ImmutableSamplerAssigned != 0;
271 }
272
273 SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const
274 {
275 return static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VariableType);
276 }
277
278 String GetPrintName(Uint32 ArrayInd) const
279 {
280 VERIFY_EXPR(ArrayInd < ArraySize);
281 if (ArraySize > 1)
282 {
283 std::stringstream ss;
284 ss << Name << '[' << ArrayInd << ']';
285 return ss.str();
286 }
287 else
288 return Name;
289 }
290
291 ShaderResourceDesc GetResourceDesc() const
292 {
293 return ShaderResourceDesc{Name, SPIRVShaderResourceAttribs::GetShaderResourceType(Type), ArraySize};
294 }
295
296 RESOURCE_DIMENSION GetResourceDimension() const
297 {
298 return static_cast<RESOURCE_DIMENSION>(ResourceDim);
299 }
300
301 bool IsMultisample() const
302 {
303 return IsMS != 0;
304 }
305
306 bool IsCompatibleWith(const VkResource& rhs) const
307 {
308 // clang-format off
309 return Binding == rhs.Binding &&
310 DescriptorSet == rhs.DescriptorSet &&
311 ArraySize == rhs.ArraySize &&
312 Type == rhs.Type;
313 // clang-format on
314 }
315
316 private:
317 void CacheUniformBuffer(IDeviceObject* pBuffer,
318 ShaderResourceCacheVk::Resource& DstRes,
319 VkDescriptorSet vkDescrSet,
320 Uint32 ArrayInd,
321 Uint16& DynamicBuffersCounter) const;
322
323 void CacheStorageBuffer(IDeviceObject* pBufferView,
324 ShaderResourceCacheVk::Resource& DstRes,
325 VkDescriptorSet vkDescrSet,
326 Uint32 ArrayInd,
327 Uint16& DynamicBuffersCounter) const;
328
329 void CacheTexelBuffer(IDeviceObject* pBufferView,
330 ShaderResourceCacheVk::Resource& DstRes,
331 VkDescriptorSet vkDescrSet,
332 Uint32 ArrayInd,
333 Uint16& DynamicBuffersCounter) const;
334
335 template <typename TCacheSampler>
336 void CacheImage(IDeviceObject* pTexView,
337 ShaderResourceCacheVk::Resource& DstRes,
338 VkDescriptorSet vkDescrSet,
339 Uint32 ArrayInd,
340 TCacheSampler CacheSampler) const;
341
342 void CacheSeparateSampler(IDeviceObject* pSampler,
343 ShaderResourceCacheVk::Resource& DstRes,
344 VkDescriptorSet vkDescrSet,
345 Uint32 ArrayInd) const;
346
347 void CacheInputAttachment(IDeviceObject* pTexView,
348 ShaderResourceCacheVk::Resource& DstRes,
349 VkDescriptorSet vkDescrSet,
350 Uint32 ArrayInd) const;
351
352 void CacheAccelerationStructure(IDeviceObject* pTLAS,
353 ShaderResourceCacheVk::Resource& DstRes,
354 VkDescriptorSet vkDescrSet,
355 Uint32 ArrayInd) const;
356
357 template <typename ObjectType, typename TPreUpdateObject>
358 bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
359 RefCntAutoPtr<ObjectType>&& pObject,
360 TPreUpdateObject PreUpdateObject) const;
361 };
362
363 // Copies static resources from SrcResourceCache defined by SrcLayout
364 // to DstResourceCache defined by this layout
365 void InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout,
366 const ShaderResourceCacheVk& SrcResourceCache,
367 ShaderResourceCacheVk& DstResourceCache) const;
368
369 #ifdef DILIGENT_DEVELOPMENT
370 bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const;
371 static void dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages,
372 const PipelineResourceLayoutDesc& ResourceLayoutDesc,
373 bool VerifyVariables,
374 bool VerifyImmutableSamplers);
375 #endif
376
377 Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
378 {
379 return m_NumResources[VarType];
380 }
381
382 // Initializes resource slots in the ResourceCache
383 void InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache) const;
384
385 // Writes dynamic resource descriptors from ResourceCache to vkDynamicDescriptorSet
386 void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
387 VkDescriptorSet vkDynamicDescriptorSet) const;
388
389 const Char* GetShaderName() const
390 {
391 return GetStringPoolData();
392 }
393
394 SHADER_TYPE GetShaderType() const { return m_ShaderType; }
395
396 const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
397 {
398 VERIFY_EXPR(r < m_NumResources[VarType]);
399 auto* Resources = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get());
400 return Resources[GetResourceOffset(VarType, r)];
401 }
402
403 bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; }
404
405 bool IsCompatibleWith(const ShaderResourceLayoutVk& ResLayout) const;
406
407 private:
408 Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
409 {
410 VERIFY_EXPR(r < m_NumResources[VarType]);
411 static_assert(SHADER_RESOURCE_VARIABLE_TYPE_STATIC == 0, "SHADER_RESOURCE_VARIABLE_TYPE_STATIC == 0 expected");
412 r += (VarType > SHADER_RESOURCE_VARIABLE_TYPE_STATIC) ? m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] : 0;
413 static_assert(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE == 1, "SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE == 1 expected");
414 r += (VarType > SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) ? m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] : 0;
415 return r;
416 }
417 VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r)
418 {
419 VERIFY_EXPR(r < m_NumResources[VarType]);
420 auto* Resources = reinterpret_cast<VkResource*>(m_ResourceBuffer.get());
421 return Resources[GetResourceOffset(VarType, r)];
422 }
423
424 const VkResource& GetResource(Uint32 r) const
425 {
426 VERIFY_EXPR(r < GetTotalResourceCount());
427 const auto* Resources = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get());
428 return Resources[r];
429 }
430
431 Uint32 GetTotalResourceCount() const
432 {
433 return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
434 }
435
436 const char* GetStringPoolData() const
437 {
438 const auto* ResourceDataEnd = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get()) + GetTotalResourceCount();
439 const auto* SamplerDataEnd = reinterpret_cast<const ImmutableSamplerPtrType*>(ResourceDataEnd) + m_NumImmutableSamplers;
440 return reinterpret_cast<const char*>(SamplerDataEnd);
441 }
442
443 static constexpr const Uint32 InvalidResourceIndex = ~0u;
444
445 // Maps resource name to its index in m_ResourceBuffer
446 using ResourceNameToIndex_t = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>;
447 StringPool AllocateMemory(const std::vector<const ShaderVkImpl*>& Shaders,
448 IMemoryAllocator& Allocator,
449 const PipelineResourceLayoutDesc& ResourceLayoutDesc,
450 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
451 Uint32 NumAllowedTypes,
452 ResourceNameToIndex_t& UniqueNames,
453 bool AllocateImmutableSamplers);
454
455 using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
456 ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept
457 {
458 VERIFY(n < m_NumImmutableSamplers, "Immutable sampler index (", n, ") is out of range. Total immutable sampler count: ", m_NumImmutableSamplers);
459 auto* ResourceMemoryEnd = reinterpret_cast<VkResource*>(m_ResourceBuffer.get()) + GetTotalResourceCount();
460 return reinterpret_cast<ImmutableSamplerPtrType*>(ResourceMemoryEnd)[n];
461 }
462
463 // clang-format off
464 /* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
465 /* 8 */ std::unique_ptr<void, STDDeleterRawMem<void>> m_ResourceBuffer;
466
467 /*24 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
468
469 /*32 */ Uint16 m_NumImmutableSamplers = 0;
470 /*34 */ bool m_IsUsingSeparateSamplers = false;
471 /*36 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN;
472
473 /*40 */ // End of class
474 // clang-format on
475 };
476
477 } // namespace Diligent
6060
6161 #include <memory>
6262
63 #include "ShaderResourceLayoutVk.hpp"
6463 #include "ShaderResourceVariableBase.hpp"
64 #include "ShaderResourceCacheVk.hpp"
6565
6666 namespace Diligent
6767 {
6868
6969 class ShaderVariableVkImpl;
70 class PipelineResourceSignatureVkImpl;
7071
7172 // sizeof(ShaderVariableManagerVk) == 32 (x64, msvc, Release)
7273 class ShaderVariableManagerVk
7879 m_ResourceCache{ResourceCache}
7980 {}
8081
81 void Initialize(const ShaderResourceLayoutVk& SrcLayout,
82 IMemoryAllocator& Allocator,
83 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
84 Uint32 NumAllowedTypes);
82 void Initialize(const PipelineResourceSignatureVkImpl& SrcLayout,
83 IMemoryAllocator& Allocator,
84 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
85 Uint32 NumAllowedTypes);
8586
8687 ~ShaderVariableManagerVk();
8788
9293
9394 void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const;
9495
95 static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout,
96 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
97 Uint32 NumAllowedTypes,
98 Uint32& NumVariables);
96 static size_t GetRequiredMemorySize(const PipelineResourceSignatureVkImpl& Layout,
97 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
98 Uint32 NumAllowedTypes,
99 Uint32& NumVariables);
99100
100101 Uint32 GetVariableCount() const { return m_NumVariables; }
101102
102103 private:
103104 friend ShaderVariableVkImpl;
105 using PackedBindingIndex = PipelineResourceSignatureVkImpl::PackedBindingIndex;
104106
105107 Uint32 GetVariableIndex(const ShaderVariableVkImpl& Variable);
106108
109 const PipelineResourceDesc& GetResource(Uint32 Index) const
110 {
111 VERIFY_EXPR(m_pSignature);
112 return m_pSignature->GetResource(Index);
113 }
114 const PackedBindingIndex& GetBinding(Uint32 Index) const
115 {
116 VERIFY_EXPR(m_pSignature);
117 return m_pSignature->GetBinding(Index);
118 }
119
120 private:
121 PipelineResourceSignatureVkImpl const* m_pSignature = nullptr;
122
107123 IObject& m_Owner;
124
108125 // Variable mgr is owned by either Pipeline state object (in which case m_ResourceCache references
109126 // static resource cache owned by the same PSO object), or by SRB object (in which case
110127 // m_ResourceCache references the cache in the SRB). Thus the cache and the resource layout
122139 #endif
123140 };
124141
125 // sizeof(ShaderVariableVkImpl) == 24 (x64)
142 // sizeof(ShaderVariableVkImpl) == 16 (x64)
126143 class ShaderVariableVkImpl final : public IShaderResourceVariable
127144 {
128145 public:
129 ShaderVariableVkImpl(ShaderVariableManagerVk& ParentManager,
130 const ShaderResourceLayoutVk::VkResource& Resource) :
131 m_ParentManager{ParentManager},
132 m_Resource{Resource}
146 explicit ShaderVariableVkImpl(ShaderVariableManagerVk& ParentManager) :
147 m_ParentManager{ParentManager}
133148 {}
134149
135150 // clang-format off
170185
171186 virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final
172187 {
173 return m_Resource.GetVariableType();
174 }
175
176 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
177 {
178 m_Resource.BindResource(pObject, 0, m_ParentManager.m_ResourceCache);
179 }
188 return GetDesc().VarType;
189 }
190
191 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final;
180192
181193 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
182194 Uint32 FirstElement,
183 Uint32 NumElements) override final
184 {
185 VerifyAndCorrectSetArrayArguments(m_Resource.Name, m_Resource.ArraySize, FirstElement, NumElements);
186 for (Uint32 Elem = 0; Elem < NumElements; ++Elem)
187 m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache);
188 }
195 Uint32 NumElements) override final;
189196
190197 virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final
191198 {
192 ResourceDesc = m_Resource.GetResourceDesc();
199 const auto& Desc = GetDesc();
200 ResourceDesc.Name = Desc.Name;
201 ResourceDesc.Type = Desc.ResourceType;
202 ResourceDesc.ArraySize = Desc.ArraySize;
193203 }
194204
195205 virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
196206 {
197 return m_ParentManager.GetVariableIndex(*this);
198 }
199
200 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
201 {
202 return m_Resource.IsBound(ArrayIndex, m_ParentManager.m_ResourceCache);
203 }
204
205 const ShaderResourceLayoutVk::VkResource& GetResource() const
206 {
207 return m_Resource;
208 }
207 VERIFY_EXPR(m_ParentManager.m_pVariables);
208 return Uint32(size_t(this - m_ParentManager.m_pVariables));
209 }
210
211 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final;
212
213 String GetPrintName(Uint32 ArrayInd) const;
214
215 RESOURCE_DIMENSION GetResourceDimension() const;
216
217 bool IsMultisample() const;
209218
210219 private:
211220 friend ShaderVariableManagerVk;
212
213 ShaderVariableManagerVk& m_ParentManager;
214 const ShaderResourceLayoutVk::VkResource& m_Resource;
221 using PackedBindingIndex = PipelineResourceSignatureVkImpl::PackedBindingIndex;
222
223 const PipelineResourceDesc& GetDesc() const { return m_ParentManager.GetResource(GetIndex()); }
224 const PackedBindingIndex& GetBinding() const { return m_ParentManager.GetBinding(GetIndex()); }
225
226 void BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const;
227
228 struct UpdateInfo
229 {
230 ShaderResourceCacheVk::Resource& DstRes;
231 const VkDescriptorSet vkDescrSet;
232 const Uint32 ArrayIndex;
233 const SHADER_RESOURCE_VARIABLE_TYPE VarType;
234 const Uint16 Binding;
235 const Uint8 SamplerInd;
236 char const* const Name;
237 };
238
239 void CacheUniformBuffer(IDeviceObject* pBuffer,
240 UpdateInfo& Info,
241 Uint16& DynamicBuffersCounter) const;
242
243 void CacheStorageBuffer(IDeviceObject* pBufferView,
244 UpdateInfo& Info,
245 Uint16& DynamicBuffersCounter) const;
246
247 void CacheTexelBuffer(IDeviceObject* pBufferView,
248 UpdateInfo& Info,
249 Uint16& DynamicBuffersCounter) const;
250
251 template <typename TCacheSampler>
252 void CacheImage(IDeviceObject* pTexView,
253 UpdateInfo& Info,
254 TCacheSampler CacheSampler) const;
255
256 void CacheSeparateSampler(IDeviceObject* pSampler,
257 UpdateInfo& Info) const;
258
259 void CacheInputAttachment(IDeviceObject* pTexView,
260 UpdateInfo& Info) const;
261
262 void CacheAccelerationStructure(IDeviceObject* pTLAS,
263 UpdateInfo& Info) const;
264
265 template <typename ObjectType, typename TPreUpdateObject>
266 bool UpdateCachedResource(UpdateInfo& Info,
267 RefCntAutoPtr<ObjectType>&& pObject,
268 TPreUpdateObject PreUpdateObject) const;
269
270 bool IsImmutableSamplerAssigned() const;
271
272 // Updates resource descriptor in the descriptor set
273 inline void UpdateDescriptorHandle(UpdateInfo& Info,
274 const VkDescriptorImageInfo* pImageInfo,
275 const VkDescriptorBufferInfo* pBufferInfo,
276 const VkBufferView* pTexelBufferView,
277 const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const;
278
279 static constexpr Uint8 InvalidSamplerInd = PipelineResourceSignatureVkImpl::InvalidSamplerInd;
280
281 private:
282 ShaderVariableManagerVk& m_ParentManager;
215283 };
216284
217285 } // namespace Diligent
6767 return m_SPIRV;
6868 }
6969
70 const std::shared_ptr<const SPIRVShaderResources>& GetShaderResources() const { return m_pShaderResources; }
70 const SPIRVShaderResources& GetShaderResources() const { return *m_pShaderResources; }
7171
7272 const char* GetEntryPoint() const { return m_EntryPoint.c_str(); }
7373
7474 private:
7575 void MapHLSLVertexShaderInputs();
7676
77 // SPIRVShaderResources class instance must be referenced through the shared pointer, because
78 // it is referenced by ShaderResourceLayoutVk class instances
77 // AZ TODO: remove shared pointer
7978 std::shared_ptr<const SPIRVShaderResources> m_pShaderResources;
8079
8180 std::string m_EntryPoint;
8686
8787
8888 VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType);
89 VkShaderStageFlags ShaderTypesToVkShaderStageFlags(SHADER_TYPE ShaderTypes);
8990
9091 VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags);
9192 VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags);
230230 void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
231231 {
232232 auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
233 BindShaderResources(pPipelineStateVk);
234
233235 if (PipelineStateVkImpl::IsSameObject(m_pPipelineState, pPipelineStateVk))
234236 return;
235237
305307 default:
306308 UNEXPECTED("unknown pipeline type");
307309 }
308
309 m_DescrSetBindInfo.Reset();
310 }
311
312 void DeviceContextVkImpl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
313 {
314 DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must mot be null");
310 }
311
312 static Uint32 PipelineTypeToBindPointIndex(PIPELINE_TYPE Type)
313 {
314 const Uint8 Indices[] = {
315 0, // PIPELINE_TYPE_GRAPHICS
316 1, // PIPELINE_TYPE_COMPUTE
317 0, // PIPELINE_TYPE_MESH
318 2 // PIPELINE_TYPE_RAY_TRACING
319 };
320 static_assert(_countof(Indices) == Uint32{PIPELINE_TYPE_LAST} + 1, "AZ TODO");
321 return Indices[Uint32{Type}];
322 }
323
324 static VkPipelineBindPoint PipelineTypeToBindPoint(PIPELINE_TYPE Type)
325 {
326 const VkPipelineBindPoint BindPoints[] = {
327 VK_PIPELINE_BIND_POINT_GRAPHICS, // PIPELINE_TYPE_GRAPHICS
328 VK_PIPELINE_BIND_POINT_COMPUTE, // PIPELINE_TYPE_COMPUTE
329 VK_PIPELINE_BIND_POINT_GRAPHICS, // PIPELINE_TYPE_MESH
330 VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR // PIPELINE_TYPE_RAY_TRACING
331 };
332 static_assert(_countof(BindPoints) == Uint32{PIPELINE_TYPE_LAST} + 1, "AZ TODO");
333 return BindPoints[Uint32{Type}];
334 }
335
336 void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* pPipelineStateVk)
337 {
338 VERIFY_EXPR(pPipelineStateVk != nullptr);
339
340 const auto& Layout = pPipelineStateVk->GetPipelineLayout();
341 auto& Resources = m_ShaderResources[PipelineTypeToBindPointIndex(Layout.GetPipelineType())];
342 auto& DescrSetBindInfo = m_DescrSetBindInfo[PipelineTypeToBindPointIndex(Layout.GetPipelineType())];
343
344 #ifdef DILIGENT_DEVELOPMENT
345 for (Uint32 i = 0, Count = Layout.GetSignatureCount(); i < Count; ++i)
346 {
347 auto* LayoutSign = Layout.GetSignature(i);
348 auto* ResSign = Resources[i] ? Resources[i]->GetPipelineResourceSignature() : nullptr;
349
350 if (LayoutSign != ResSign)
351 {
352 LOG_ERROR_MESSAGE("Shader resource binding '", (ResSign ? ResSign->GetDesc().Name : ""),
353 "' is not compatible with pipeline layout in current pipeline '", pPipelineStateVk->GetDesc().Name, "'.");
354 Resources[i] = nullptr;
355 }
356 }
357 #endif
358
359 // the number of bound descriptor sets and dynamic offsets may be greater then actually used in pipeline layout,
360 // see https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#descriptorsets-compatibility
361 VERIFY_EXPR(Layout.GetDescriptorSetCount() <= DescrSetBindInfo.SetCout);
362 VERIFY_EXPR(Layout.GetDynamicOffsetCount() <= DescrSetBindInfo.DynamicOffsetCount);
363
364 // AZ TODO: optimize - bind DS that was changed
365 GetCommandBuffer().BindDescriptorSets(PipelineTypeToBindPoint(Layout.GetPipelineType()), Layout.GetVkPipelineLayout(), 0, Layout.GetDescriptorSetCount(), DescrSetBindInfo.vkSets.data(), Layout.GetDynamicOffsetCount(), DescrSetBindInfo.DynamicOffsets.data());
366 }
367
368 void DeviceContextVkImpl::TransitionShaderResources(IPipelineState*, IShaderResourceBinding* pShaderResourceBinding)
369 {
370 #ifdef DILIGENT_DEVELOPMENT
315371 if (m_pActiveRenderPass)
316372 {
317373 LOG_ERROR_MESSAGE("State transitions are not allowed inside a render pass.");
318374 return;
319375 }
320376
321 auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
322 pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, false, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, nullptr);
377 if (pShaderResourceBinding == nullptr)
378 {
379 LOG_ERROR_MESSAGE("TODO");
380 return;
381 }
382 #endif
383
384 auto* pResBindingVkImpl = ValidatedCast<ShaderResourceBindingVkImpl>(pShaderResourceBinding);
385 auto& ResourceCache = pResBindingVkImpl->GetResourceCache();
386
387 ResourceCache.TransitionResources<false>(this);
323388 }
324389
325390 void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
327392 if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
328393 return;
329394
330 m_pPipelineState->CommitAndTransitionShaderResources(pShaderResourceBinding, this, true, StateTransitionMode, &m_DescrSetBindInfo);
395 auto* pResBindingVkImpl = ValidatedCast<ShaderResourceBindingVkImpl>(pShaderResourceBinding);
396 auto& ResourceCache = pResBindingVkImpl->GetResourceCache();
397
398 #ifdef DILIGENT_DEBUG
399 ResourceCache.DbgVerifyDynamicBuffersCounter();
400 #endif
401
402 if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
403 {
404 ResourceCache.TransitionResources<false>(this);
405 }
406 #ifdef DILIGENT_DEVELOPMENT
407 else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
408 {
409 ResourceCache.TransitionResources<true>(this);
410 }
411 #endif