Skip to content

Commit 0324728

Browse files
committed
Add vulkan inline constants support, emulated with uniform buffers. (PushConstants not impl yet)
1 parent 68a2c34 commit 0324728

File tree

9 files changed

+1530
-20
lines changed

9 files changed

+1530
-20
lines changed

Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,9 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
555555
__forceinline ResourceBindInfo& GetBindInfo(PIPELINE_TYPE Type);
556556

557557
__forceinline void CommitDescriptorSets(ResourceBindInfo& BindInfo, Uint32 CommitSRBMask);
558+
559+
void UpdateInlineConstantBuffers(ResourceBindInfo& BindInfo);
560+
558561
#ifdef DILIGENT_DEVELOPMENT
559562
void DvpValidateCommittedShaderResources(ResourceBindInfo& BindInfo);
560563
#endif

Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace Diligent
5050

5151
struct SPIRVShaderResourceAttribs;
5252
class DeviceContextVkImpl;
53+
class BufferVkImpl;
5354

5455
struct ImmutableSamplerAttribsVk
5556
{
@@ -58,6 +59,17 @@ struct ImmutableSamplerAttribsVk
5859
};
5960
ASSERT_SIZEOF(ImmutableSamplerAttribsVk, 8, "The struct is used in serialization and must be tightly packed");
6061

62+
/// Inline constant buffer attributes for Vulkan backend.
63+
/// Since Vulkan only supports one push constant block per pipeline, inline constants
64+
/// are emulated using dynamic uniform buffers (similar to D3D11 backend).
65+
struct InlineConstantBufferAttribsVk
66+
{
67+
Uint32 DescrSet = 0; // Descriptor set index
68+
Uint32 BindingIndex = 0; // Binding index within the descriptor set
69+
Uint32 NumConstants = 0; // Number of 32-bit constants
70+
RefCntAutoPtr<BufferVkImpl> pBuffer; // Internal dynamic uniform buffer
71+
};
72+
6173
struct PipelineResourceSignatureInternalDataVk : PipelineResourceSignatureInternalData<PipelineResourceAttribsVk, ImmutableSamplerAttribsVk>
6274
{
6375
Uint16 DynamicUniformBufferCount = 0;
@@ -134,6 +146,16 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
134146
void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
135147
VkDescriptorSet vkDynamicDescriptorSet) const;
136148

149+
// Updates inline constant buffers by mapping the internal buffers and copying data from the resource cache
150+
void UpdateInlineConstantBuffers(const ShaderResourceCacheVk& ResourceCache,
151+
DeviceContextVkImpl& Ctx) const;
152+
153+
// Returns the number of inline constant buffers
154+
Uint32 GetNumInlineConstantBuffers() const { return m_NumInlineConstantBuffers; }
155+
156+
// Returns the inline constant buffer attributes
157+
const InlineConstantBufferAttribsVk* GetInlineConstantBuffers() const { return m_InlineConstantBuffers.get(); }
158+
137159
#ifdef DILIGENT_DEVELOPMENT
138160
/// Verifies committed resource using the SPIRV resource attributes from the PSO.
139161
bool DvpValidateCommittedResource(const DeviceContextVkImpl* pDeviceCtx,
@@ -193,6 +215,15 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
193215
// The total number storage buffers with dynamic offsets in both descriptor sets,
194216
// accounting for array size.
195217
Uint16 m_DynamicStorageBufferCount = 0;
218+
219+
// Number of inline constant buffers
220+
Uint32 m_NumInlineConstantBuffers = 0;
221+
// Inline constant buffer attributes
222+
std::unique_ptr<InlineConstantBufferAttribsVk[]> m_InlineConstantBuffers;
223+
224+
// Pointer to CPU-side staging buffer for static inline constants
225+
// This memory is allocated in CreateSetLayouts and must be freed in Destruct
226+
void* m_pStaticInlineConstantData = nullptr;
196227
};
197228

198229
template <> Uint32 PipelineResourceSignatureVkImpl::GetDescriptorSetIndex<PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_STATIC_MUTABLE>() const;

Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
7474
public:
7575
explicit ShaderResourceCacheVk(ResourceCacheContentType ContentType) noexcept :
7676
m_TotalResources{0},
77-
m_ContentType{static_cast<Uint32>(ContentType)}
77+
m_ContentType{static_cast<Uint32>(ContentType)},
78+
m_HasInlineConstants{0}
7879
{
7980
VERIFY_EXPR(GetContentType() == ContentType);
8081
}
@@ -93,7 +94,7 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
9394
void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, const Uint32* SetSizes);
9495
void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type, bool HasImmutableSampler);
9596

96-
// sizeof(Resource) == 32 (x64, msvc, Release)
97+
// sizeof(Resource) == 40 (x64, msvc, Release)
9798
struct Resource
9899
{
99100
explicit Resource(DescriptorType _Type, bool _HasImmutableSampler) noexcept :
@@ -120,6 +121,10 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
120121
/*16 */ Uint64 BufferBaseOffset = 0;
121122
/*24 */ Uint64 BufferRangeSize = 0;
122123

124+
// For inline constants only - pointer to CPU-side staging buffer
125+
/*32 */ void* pInlineConstantData = nullptr;
126+
/*40 */ // End of structure
127+
123128
VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo() const;
124129
VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo() const;
125130
VkDescriptorImageInfo GetImageDescriptorWriteInfo () const;
@@ -245,13 +250,36 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
245250
Uint32 CacheOffset,
246251
Uint32 DynamicBufferOffset);
247252

253+
// Sets inline constant data in the resource cache
254+
void SetInlineConstants(Uint32 DescrSetIndex,
255+
Uint32 CacheOffset,
256+
const void* pConstants,
257+
Uint32 FirstConstant,
258+
Uint32 NumConstants);
259+
260+
// Gets the inline constant data pointer from the resource cache
261+
const void* GetInlineConstantData(Uint32 DescrSetIndex, Uint32 BindingIndex) const;
262+
263+
// Initialize inline constant buffer in the resource cache
264+
void InitializeInlineConstantBuffer(Uint32 DescrSetIndex,
265+
Uint32 CacheOffset,
266+
Uint32 NumConstants,
267+
void* pInlineConstantData);
268+
269+
// Sets the inline constant memory block (takes ownership, will be freed in destructor)
270+
void SetInlineConstantMemory(IMemoryAllocator& Allocator, void* pMemory)
271+
{
272+
m_pInlineConstantMemory = decltype(m_pInlineConstantMemory){
273+
pMemory,
274+
STDDeleter<void, IMemoryAllocator>(Allocator)};
275+
}
248276

249277
Uint32 GetNumDescriptorSets() const { return m_NumSets; }
250278
bool HasDynamicResources() const { return m_NumDynamicBuffers > 0; }
251279

252280
bool HasInlineConstants() const
253281
{
254-
return false;
282+
return m_HasInlineConstants;
255283
}
256284

257285
ResourceCacheContentType GetContentType() const { return static_cast<ResourceCacheContentType>(m_ContentType); }
@@ -287,16 +315,22 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
287315

288316
std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
289317

318+
// Memory for inline constant data (allocated separately, freed in destructor)
319+
std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pInlineConstantMemory;
320+
290321
Uint16 m_NumSets = 0;
291322

292323
// Total actual number of dynamic buffers (that were created with USAGE_DYNAMIC) bound in the resource cache
293324
// regardless of the variable type. Note this variable is not equal to dynamic offsets count, which is constant.
294325
Uint16 m_NumDynamicBuffers = 0;
295-
Uint32 m_TotalResources : 31;
326+
Uint32 m_TotalResources : 30;
296327

297328
// Indicates what types of resources are stored in the cache
298329
const Uint32 m_ContentType : 1;
299330

331+
// Indicates whether the cache contains inline constants
332+
Uint32 m_HasInlineConstants : 1;
333+
300334
#ifdef DILIGENT_DEBUG
301335
// Debug array that stores flags indicating if resources in the cache have been initialized
302336
std::vector<std::vector<bool>> m_DbgInitializedResources;

Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,24 @@ DeviceContextVkImpl::ResourceBindInfo& DeviceContextVkImpl::GetBindInfo(PIPELINE
415415
return m_BindInfo[Indices[Uint32{Type}]];
416416
}
417417

418+
void DeviceContextVkImpl::UpdateInlineConstantBuffers(ResourceBindInfo& BindInfo)
419+
{
420+
const Uint32 SignCount = m_pPipelineState->GetResourceSignatureCount();
421+
for (Uint32 i = 0; i < SignCount; ++i)
422+
{
423+
const PipelineResourceSignatureVkImpl* pSign = m_pPipelineState->GetResourceSignature(i);
424+
if (pSign == nullptr || pSign->GetNumInlineConstantBuffers() == 0)
425+
continue;
426+
427+
const ShaderResourceCacheVk* pResourceCache = BindInfo.ResourceCaches[i];
428+
if (pResourceCache == nullptr || !pResourceCache->HasInlineConstants())
429+
continue;
430+
431+
// Update inline constant buffers
432+
pSign->UpdateInlineConstantBuffers(*pResourceCache, *this);
433+
}
434+
}
435+
418436
void DeviceContextVkImpl::CommitDescriptorSets(ResourceBindInfo& BindInfo, Uint32 CommitSRBMask)
419437
{
420438
VERIFY(CommitSRBMask != 0, "This method should not be called when there is nothing to commit");
@@ -758,6 +776,14 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
758776
#endif
759777

760778
ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_GRAPHICS);
779+
780+
// Update inline constant buffers before binding descriptor sets
781+
const bool InlineConstantsIntact = (Flags & DRAW_FLAG_INLINE_CONSTANTS_INTACT) != 0;
782+
if (!InlineConstantsIntact)
783+
{
784+
UpdateInlineConstantBuffers(BindInfo);
785+
}
786+
761787
// First time we must always bind descriptor sets with dynamic offsets as SRBs are stale.
762788
// If there are no dynamic buffers bound in the resource cache, for all subsequent
763789
// calls we do not need to bind the sets again.
@@ -1059,6 +1085,10 @@ void DeviceContextVkImpl::PrepareForDispatchCompute()
10591085
EndRenderScope();
10601086

10611087
ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_COMPUTE);
1088+
1089+
// Update inline constant buffers before binding descriptor sets
1090+
UpdateInlineConstantBuffers(BindInfo);
1091+
10621092
if (Uint32 CommitMask = BindInfo.GetCommitMask())
10631093
{
10641094
CommitDescriptorSets(BindInfo, CommitMask);
@@ -1075,6 +1105,10 @@ void DeviceContextVkImpl::PrepareForRayTracing()
10751105
EnsureVkCmdBuffer();
10761106

10771107
ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_RAY_TRACING);
1108+
1109+
// Update inline constant buffers before binding descriptor sets
1110+
UpdateInlineConstantBuffers(BindInfo);
1111+
10781112
if (Uint32 CommitMask = BindInfo.GetCommitMask())
10791113
{
10801114
CommitDescriptorSets(BindInfo, CommitMask);

0 commit comments

Comments
 (0)