Skip to content

Commit d586cdd

Browse files
hzqstTheMostDiligent
authored andcommitted
PipelineLayoutVk: enable push constant support
1 parent ceca0c5 commit d586cdd

File tree

2 files changed

+73
-13
lines changed

2 files changed

+73
-13
lines changed

Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,7 +47,9 @@ class PipelineLayoutVk
4747
PipelineLayoutVk();
4848
~PipelineLayoutVk();
4949

50-
void Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount) noexcept(false);
50+
void Create(RenderDeviceVkImpl* pDeviceVk,
51+
RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[],
52+
Uint32 SignatureCount) noexcept(false);
5153
void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask);
5254

5355
VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; }
@@ -59,6 +61,17 @@ class PipelineLayoutVk
5961
return m_FirstDescrSetIndex[Index];
6062
}
6163

64+
struct PushConstantInfo
65+
{
66+
Uint32 Size = 0;
67+
VkShaderStageFlags StageFlags = 0;
68+
Uint32 SignatureIndex = ~0u;
69+
Uint32 ResourceIndex = ~0u;
70+
71+
constexpr explicit operator bool() const { return Size != 0; }
72+
};
73+
const PushConstantInfo& GetPushConstantInfo() const { return m_PushConstantInfo; }
74+
6275
private:
6376
VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
6477

@@ -70,6 +83,8 @@ class PipelineLayoutVk
7083
// (Maximum is MAX_RESOURCE_SIGNATURES * 2)
7184
Uint8 m_DescrSetCount = 0;
7285

86+
PushConstantInfo m_PushConstantInfo;
87+
7388
#ifdef DILIGENT_DEBUG
7489
Uint32 m_DbgMaxBindIndex = 0;
7590
#endif

Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,7 +59,9 @@ void PipelineLayoutVk::Release(RenderDeviceVkImpl* pDeviceVk, Uint64 CommandQueu
5959
}
6060
}
6161

62-
void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount) noexcept(false)
62+
void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk,
63+
RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[],
64+
Uint32 SignatureCount) noexcept(false)
6365
{
6466
VERIFY(m_DescrSetCount == 0 && !m_VkPipelineLayout, "This pipeline layout is already initialized");
6567

@@ -92,6 +94,27 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<Pipel
9294
#ifdef DILIGENT_DEBUG
9395
m_DbgMaxBindIndex = std::max(m_DbgMaxBindIndex, Uint32{pSignature->GetDesc().BindingIndex});
9496
#endif
97+
98+
// Vulkan allows only one push constant range per pipeline layout.
99+
// Diligent API allows multiple inline constant resources, so we promote only the first inline constant
100+
// from resource signatures to push constants. Other inline constants remain uniform buffers.
101+
if (!m_PushConstantInfo)
102+
{
103+
for (Uint32 r = 0; r < pSignature->GetTotalResourceCount(); ++r)
104+
{
105+
const PipelineResourceDesc& ResDesc = pSignature->GetResourceDesc(r);
106+
if (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS)
107+
{
108+
VERIFY_EXPR(ResDesc.ArraySize > 0);
109+
// For inline constants, ArraySize contains the number of 32-bit constants.
110+
m_PushConstantInfo.Size = ResDesc.ArraySize * sizeof(Uint32);
111+
m_PushConstantInfo.StageFlags = ShaderTypesToVkShaderStageFlags(ResDesc.ShaderStages);
112+
m_PushConstantInfo.SignatureIndex = BindInd;
113+
m_PushConstantInfo.ResourceIndex = r;
114+
break;
115+
}
116+
}
117+
}
95118
}
96119
VERIFY_EXPR(DescSetLayoutCount <= MAX_RESOURCE_SIGNATURES * 2);
97120

@@ -114,19 +137,41 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<Pipel
114137
") used by the pipeline layout exceeds device limit (", Limits.maxDescriptorSetStorageBuffersDynamic, ")");
115138
}
116139

140+
// Validate push constant size against device limits
141+
if (m_PushConstantInfo.Size > Limits.maxPushConstantsSize)
142+
{
143+
LOG_ERROR_AND_THROW("Push constant size (", m_PushConstantInfo.Size,
144+
" bytes) exceeds device limit (", Limits.maxPushConstantsSize, " bytes)");
145+
}
146+
117147
VERIFY(m_DescrSetCount <= std::numeric_limits<decltype(m_DescrSetCount)>::max(),
118148
"Descriptor set count (", DescSetLayoutCount, ") exceeds the maximum representable value");
119149

120-
VkPipelineLayoutCreateInfo PipelineLayoutCI = {};
150+
VkPipelineLayoutCreateInfo PipelineLayoutCI{};
151+
PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
152+
PipelineLayoutCI.pNext = nullptr;
153+
PipelineLayoutCI.flags = 0; // reserved for future use
154+
PipelineLayoutCI.setLayoutCount = DescSetLayoutCount;
155+
PipelineLayoutCI.pSetLayouts = DescSetLayoutCount ? DescSetLayouts.data() : nullptr;
156+
157+
// Set up push constant range if present
158+
VkPushConstantRange PushConstantRange{};
159+
if (m_PushConstantInfo)
160+
{
161+
PushConstantRange.stageFlags = m_PushConstantInfo.StageFlags;
162+
PushConstantRange.offset = 0;
163+
PushConstantRange.size = m_PushConstantInfo.Size;
164+
165+
PipelineLayoutCI.pushConstantRangeCount = 1;
166+
PipelineLayoutCI.pPushConstantRanges = &PushConstantRange;
167+
}
168+
else
169+
{
170+
PipelineLayoutCI.pushConstantRangeCount = 0;
171+
PipelineLayoutCI.pPushConstantRanges = nullptr;
172+
}
121173

122-
PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
123-
PipelineLayoutCI.pNext = nullptr;
124-
PipelineLayoutCI.flags = 0; // reserved for future use
125-
PipelineLayoutCI.setLayoutCount = DescSetLayoutCount;
126-
PipelineLayoutCI.pSetLayouts = DescSetLayoutCount ? DescSetLayouts.data() : nullptr;
127-
PipelineLayoutCI.pushConstantRangeCount = 0;
128-
PipelineLayoutCI.pPushConstantRanges = nullptr;
129-
m_VkPipelineLayout = pDeviceVk->GetLogicalDevice().CreatePipelineLayout(PipelineLayoutCI);
174+
m_VkPipelineLayout = pDeviceVk->GetLogicalDevice().CreatePipelineLayout(PipelineLayoutCI);
130175

131176
m_DescrSetCount = static_cast<Uint8>(DescSetLayoutCount);
132177
}

0 commit comments

Comments
 (0)