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