Skip to content

Commit 8bd7c90

Browse files
committed
adding support for push constants to SPIRVShaderResources.
1 parent 437a562 commit 8bd7c90

File tree

2 files changed

+228
-78
lines changed

2 files changed

+228
-78
lines changed

Graphics/ShaderTools/include/SPIRVShaderResources.hpp

Lines changed: 104 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232

3333
// SPIRVShaderResources class uses continuous chunk of memory to store all resources, as follows:
3434
//
35-
// m_MemoryBuffer m_TotalResources
36-
// | | |
37-
// | Uniform Buffers | Storage Buffers | Storage Images | Sampled Images | Atomic Counters | Separate Samplers | Separate Images | Stage Inputs | Resource Names |
35+
// m_MemoryBuffer m_TotalResources
36+
// | | |
37+
// | Uniform Buffers | Storage Buffers | Storage Images | Sampled Images | Atomic Counters | Separate Samplers | Separate Images | Input Attachments | Accel Structs | Push Constants | Stage Inputs | Resource Names |
3838

3939
#include <memory>
4040
#include <vector>
@@ -79,6 +79,7 @@ struct SPIRVShaderResourceAttribs
7979
SeparateSampler,
8080
InputAttachment,
8181
AccelerationStructure,
82+
PushConstant, // Vulkan push constant buffer - special inline constant that uses vkCmdPushConstants
8283
NumResourceTypes
8384
};
8485

@@ -111,6 +112,11 @@ struct SPIRVShaderResourceAttribs
111112
Uint32 _BufferStaticSize = 0,
112113
Uint32 _BufferStride = 0) noexcept;
113114

115+
// Constructor for push constants (no binding or descriptor set decoration)
116+
SPIRVShaderResourceAttribs(const char* _Name,
117+
ResourceType _Type,
118+
Uint32 _BufferStaticSize) noexcept;
119+
114120
ShaderResourceDesc GetResourceDesc() const
115121
{
116122
return ShaderResourceDesc{Name, GetShaderResourceType(Type), ArraySize};
@@ -125,6 +131,39 @@ struct SPIRVShaderResourceAttribs
125131
{
126132
return IsMS != 0;
127133
}
134+
135+
Uint32 GetConstantBufferSize() const
136+
{
137+
VERIFY((Type == PushConstant || Type == UniformBuffer), "Invalid resource type: PushConstant or UniformBuffer expected");
138+
return BufferStaticSize;
139+
}
140+
141+
Uint32 GetInlineConstantCountOrThrow(const char* ShaderName) const
142+
{
143+
VERIFY_EXPR(Type == PushConstant || Type == UniformBuffer);
144+
145+
if (ArraySize != 1)
146+
{
147+
LOG_ERROR_AND_THROW("Inline constants resource '", Name, "' in shader '", ShaderName, "' can not be an array.");
148+
}
149+
const Uint32 NumConstants = GetConstantBufferSize() / sizeof(Uint32);
150+
151+
constexpr Uint32 kMaxInlineConstants = 64;
152+
if (NumConstants > kMaxInlineConstants)
153+
{
154+
LOG_ERROR_AND_THROW("Inline constants resource '", Name, "' in shader '", ShaderName, "' has ",
155+
NumConstants, " constants. The maximum supported number of inline constants is ",
156+
kMaxInlineConstants, '.');
157+
}
158+
159+
if (NumConstants == 0)
160+
{
161+
LOG_ERROR_AND_THROW("Resource '", Name, "' in shader '", ShaderName,
162+
"' is marked as inline constants, but has zero buffer size. ");
163+
}
164+
165+
return NumConstants;
166+
}
128167
};
129168
static_assert(sizeof(SPIRVShaderResourceAttribs) % sizeof(void*) == 0, "Size of SPIRVShaderResourceAttribs struct must be multiple of sizeof(void*)");
130169

@@ -166,28 +205,30 @@ class SPIRVShaderResources
166205

167206
// clang-format off
168207

169-
Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); }
170-
Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); }
171-
Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); }
172-
Uint32 GetNumSmpldImgs ()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); }
173-
Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); }
174-
Uint32 GetNumSepSmplrs ()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset);}
175-
Uint32 GetNumSepImgs ()const noexcept{ return (m_InputAttachmentOffset - m_SeparateImageOffset); }
176-
Uint32 GetNumInptAtts ()const noexcept{ return (m_AccelStructOffset - m_InputAttachmentOffset);}
177-
Uint32 GetNumAccelStructs()const noexcept{ return (m_TotalResources - m_AccelStructOffset); }
208+
Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); }
209+
Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); }
210+
Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); }
211+
Uint32 GetNumSmpldImgs ()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); }
212+
Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); }
213+
Uint32 GetNumSepSmplrs ()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset); }
214+
Uint32 GetNumSepImgs ()const noexcept{ return (m_InputAttachmentOffset - m_SeparateImageOffset); }
215+
Uint32 GetNumInptAtts ()const noexcept{ return (m_AccelStructOffset - m_InputAttachmentOffset); }
216+
Uint32 GetNumAccelStructs ()const noexcept{ return (m_PushConstantOffset - m_AccelStructOffset); }
217+
Uint32 GetNumPushConstants()const noexcept{ return (m_TotalResources - m_PushConstantOffset); }
178218
Uint32 GetTotalResources () const noexcept { return m_TotalResources; }
179219
Uint32 GetNumShaderStageInputs()const noexcept { return m_NumShaderStageInputs; }
180220

181-
const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); }
182-
const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); }
183-
const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); }
184-
const SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); }
185-
const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
186-
const SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); }
187-
const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
188-
const SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); }
189-
const SPIRVShaderResourceAttribs& GetAccelStruct(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); }
190-
const SPIRVShaderResourceAttribs& GetResource (Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
221+
const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); }
222+
const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); }
223+
const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); }
224+
const SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); }
225+
const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
226+
const SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset ); }
227+
const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
228+
const SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset ); }
229+
const SPIRVShaderResourceAttribs& GetAccelStruct (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); }
230+
const SPIRVShaderResourceAttribs& GetPushConstant(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumPushConstants(), m_PushConstantOffset ); }
231+
const SPIRVShaderResourceAttribs& GetResource (Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
191232

192233
// clang-format on
193234

@@ -217,15 +258,16 @@ class SPIRVShaderResources
217258

218259
struct ResourceCounters
219260
{
220-
Uint32 NumUBs = 0;
221-
Uint32 NumSBs = 0;
222-
Uint32 NumImgs = 0;
223-
Uint32 NumSmpldImgs = 0;
224-
Uint32 NumACs = 0;
225-
Uint32 NumSepSmplrs = 0;
226-
Uint32 NumSepImgs = 0;
227-
Uint32 NumInptAtts = 0;
228-
Uint32 NumAccelStructs = 0;
261+
Uint32 NumUBs = 0;
262+
Uint32 NumSBs = 0;
263+
Uint32 NumImgs = 0;
264+
Uint32 NumSmpldImgs = 0;
265+
Uint32 NumACs = 0;
266+
Uint32 NumSepSmplrs = 0;
267+
Uint32 NumSepImgs = 0;
268+
Uint32 NumInptAtts = 0;
269+
Uint32 NumAccelStructs = 0;
270+
Uint32 NumPushConstants = 0; // Vulkan push constant buffers (max 1 per Vulkan spec)
229271
};
230272

231273
SHADER_TYPE GetShaderType() const noexcept { return m_ShaderType; }
@@ -243,16 +285,18 @@ class SPIRVShaderResources
243285
typename THandleSepSmpl,
244286
typename THandleSepImg,
245287
typename THandleInptAtt,
246-
typename THandleAccelStruct>
247-
void ProcessResources(THandleUB HandleUB,
248-
THandleSB HandleSB,
249-
THandleImg HandleImg,
250-
THandleSmplImg HandleSmplImg,
251-
THandleAC HandleAC,
252-
THandleSepSmpl HandleSepSmpl,
253-
THandleSepImg HandleSepImg,
254-
THandleInptAtt HandleInptAtt,
255-
THandleAccelStruct HandleAccelStruct) const
288+
typename THandleAccelStruct,
289+
typename THandlePushConstant>
290+
void ProcessResources(THandleUB HandleUB,
291+
THandleSB HandleSB,
292+
THandleImg HandleImg,
293+
THandleSmplImg HandleSmplImg,
294+
THandleAC HandleAC,
295+
THandleSepSmpl HandleSepSmpl,
296+
THandleSepImg HandleSepImg,
297+
THandleInptAtt HandleInptAtt,
298+
THandleAccelStruct HandleAccelStruct,
299+
THandlePushConstant HandlePushConstant) const
256300
{
257301
for (Uint32 n = 0; n < GetNumUBs(); ++n)
258302
{
@@ -308,7 +352,13 @@ class SPIRVShaderResources
308352
HandleAccelStruct(AccelStruct, n);
309353
}
310354

311-
static_assert(Uint32{SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes} == 12, "Please handle the new resource type here, if needed");
355+
for (Uint32 n = 0; n < GetNumPushConstants(); ++n)
356+
{
357+
const SPIRVShaderResourceAttribs& PushConstant = GetPushConstant(n);
358+
HandlePushConstant(PushConstant, n);
359+
}
360+
361+
static_assert(Uint32{SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes} == 13, "Please handle the new resource type here, if needed");
312362
}
313363

314364
template <typename THandler>
@@ -359,16 +409,17 @@ class SPIRVShaderResources
359409

360410
// clang-format off
361411

362-
SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); }
363-
SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); }
364-
SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); }
365-
SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); }
366-
SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
367-
SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); }
368-
SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
369-
SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); }
370-
SPIRVShaderResourceAttribs& GetAccelStruct(Uint32 n)noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); }
371-
SPIRVShaderResourceAttribs& GetResource (Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
412+
SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); }
413+
SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); }
414+
SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); }
415+
SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); }
416+
SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
417+
SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset ); }
418+
SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
419+
SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset ); }
420+
SPIRVShaderResourceAttribs& GetAccelStruct (Uint32 n)noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); }
421+
SPIRVShaderResourceAttribs& GetPushConstant(Uint32 n)noexcept{ return GetResAttribs(n, GetNumPushConstants(), m_PushConstantOffset ); }
422+
SPIRVShaderResourceAttribs& GetResource (Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
372423

373424
// clang-format on
374425

@@ -394,6 +445,7 @@ class SPIRVShaderResources
394445
OffsetType m_SeparateImageOffset = 0;
395446
OffsetType m_InputAttachmentOffset = 0;
396447
OffsetType m_AccelStructOffset = 0;
448+
OffsetType m_PushConstantOffset = 0;
397449
OffsetType m_TotalResources = 0;
398450
OffsetType m_NumShaderStageInputs = 0;
399451

0 commit comments

Comments
 (0)