Skip to content

Commit fb2ecee

Browse files
committed
Remove PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT, implement deferred push constant selection.
1 parent 11b5918 commit fb2ecee

17 files changed

+326
-436
lines changed

Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ String GetPipelineResourceFlagsString(PIPELINE_RESOURCE_FLAGS Flags, bool GetFul
16371637

16381638
PIPELINE_RESOURCE_FLAGS Flag = ExtractLSB(Flags);
16391639

1640-
static_assert(PIPELINE_RESOURCE_FLAG_LAST == (1u << 6), "Please update the switch below to handle the new pipeline resource flag.");
1640+
static_assert(PIPELINE_RESOURCE_FLAG_LAST == (1u << 5), "Please update the switch below to handle the new pipeline resource flag.");
16411641
switch (Flag)
16421642
{
16431643
case PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS:
@@ -1664,10 +1664,6 @@ String GetPipelineResourceFlagsString(PIPELINE_RESOURCE_FLAGS Flags, bool GetFul
16641664
Str.append(GetFullName ? "PIPELINE_RESOURCE_FLAG_GENERAL_INPUT_ATTACHMENT" : "GENERAL_INPUT_ATTACHMENT");
16651665
break;
16661666

1667-
case PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT:
1668-
Str.append(GetFullName ? "PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT" : "VULKAN_PUSH_CONSTANT");
1669-
break;
1670-
16711667
default:
16721668
UNEXPECTED("Unexpected pipeline resource flag");
16731669
}
@@ -1816,7 +1812,7 @@ PIPELINE_RESOURCE_FLAGS GetValidPipelineResourceFlags(SHADER_RESOURCE_TYPE Resou
18161812
switch (ResourceType)
18171813
{
18181814
case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER:
1819-
return PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS | PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY | PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS | PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT;
1815+
return PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS | PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY | PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS;
18201816

18211817
case SHADER_RESOURCE_TYPE_TEXTURE_SRV:
18221818
return PIPELINE_RESOURCE_FLAG_COMBINED_SAMPLER | PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY;

Graphics/GraphicsEngine/interface/PipelineResourceSignature.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,7 @@ DILIGENT_TYPED_ENUM(PIPELINE_RESOURCE_FLAGS, Uint8)
148148
/// \note This flag is only valid in Vulkan.
149149
PIPELINE_RESOURCE_FLAG_GENERAL_INPUT_ATTACHMENT = 1u << 5,
150150

151-
/// Indicates that this inline constant is a Vulkan push constant
152-
/// (declared with push_constant storage class in SPIR-V).
153-
/// This flag is must be explicitly set when creating PipelineResourceSignature
154-
/// And must be used together with PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS
155-
/// When this flag is set, the engine will use vkCmdPushConstants
156-
/// instead of a dynamic uniform buffer to update the constants.
157-
///
158-
/// \note This flag is only valid in Vulkan and is always combined with
159-
/// PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS.
160-
PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT = 1u << 6,
161-
162-
PIPELINE_RESOURCE_FLAG_LAST = PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT
151+
PIPELINE_RESOURCE_FLAG_LAST = PIPELINE_RESOURCE_FLAG_GENERAL_INPUT_ATTACHMENT
163152
};
164153
DEFINE_FLAG_ENUM_OPERATORS(PIPELINE_RESOURCE_FLAGS);
165154

Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,8 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc&
111111
": ", GetPipelineResourceFlagsString(AllowedResourceFlags, false, ", "), ".");
112112
}
113113

114-
if ((Res.Flags & PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT) != 0)
115-
{
116-
if (Res.Flags != (PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS | PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT))
117-
{
118-
LOG_PRS_ERROR_AND_THROW("Incorrect Desc.Resources[", i, "].Flags (", GetPipelineResourceFlagsString(Res.Flags),
119-
"). VULKAN_PUSH_CONSTANT flags must be combined with INLINE_CONSTANTS.");
120-
}
121-
}
122-
123114
if ((Res.Flags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) != 0)
124115
{
125-
if (Res.Flags != PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS && Res.Flags != (PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS | PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT))
126-
{
127-
LOG_PRS_ERROR_AND_THROW("Incorrect Desc.Resources[", i, "].Flags (", GetPipelineResourceFlagsString(Res.Flags),
128-
"). INLINE_CONSTANTS flag cannot be combined with flags other than VULKAN_PUSH_CONSTANT.");
129-
}
130-
131116
if (Res.ArraySize > 64)
132117
{
133118
LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].ArraySize (", Res.ArraySize,

Graphics/GraphicsEngine/src/PipelineStateBase.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -849,15 +849,6 @@ void ValidatePipelineResourceCompatibility(const PipelineResourceDesc& ResDesc,
849849
GetShaderResourceTypeLiteralName(ResDesc.ResourceType), "' specified in pipeline resource signature '", SignatureName, "'.");
850850
}
851851

852-
if ((ResourceFlags & PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT) != (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT))
853-
{
854-
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource '", ResDesc.Name,
855-
"' that is", ((ResourceFlags & PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT) ? "" : " not"),
856-
" labeled as vulkan's push constant, while the same resource specified by the pipeline resource signature '",
857-
SignatureName, "' is", ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT) ? "" : " not"),
858-
" labeled as such.");
859-
}
860-
861852
if ((ResourceFlags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER))
862853
{
863854
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource '", ResDesc.Name,

Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,17 @@ namespace Diligent
4040
class RenderDeviceVkImpl;
4141
class PipelineResourceSignatureVkImpl;
4242

43-
/// Push constant information extracted from shaders
43+
/// Push constant information extracted from shaders or selected from inline constants
4444
struct PushConstantInfoVk
4545
{
46-
VkShaderStageFlags StageFlags = 0;
47-
Uint32 Size = 0;
46+
VkShaderStageFlags StageFlags = 0;
47+
Uint32 Size = 0;
48+
Uint32 SignatureIndex = ~0u; // Index of the signature containing the push constant (~0u if none)
49+
Uint32 ResourceIndex = ~0u; // Resource index within the signature (~0u if none)
4850
};
4951

52+
static constexpr Uint32 INVALID_PUSH_CONSTANT_INDEX = ~0u;
53+
5054
/// Implementation of the Diligent::PipelineLayoutVk class
5155
class PipelineLayoutVk
5256
{
@@ -78,6 +82,14 @@ class PipelineLayoutVk
7882
// Returns the shader stage flags for push constants
7983
VkShaderStageFlags GetPushConstantStageFlags() const { return m_PushConstantStageFlags; }
8084

85+
// Returns the signature index containing the push constant resource
86+
// Returns INVALID_PUSH_CONSTANT_INDEX if no push constant is selected
87+
Uint32 GetPushConstantSignatureIndex() const { return m_PushConstantSignatureIndex; }
88+
89+
// Returns the resource index within the signature for push constant
90+
// Returns INVALID_PUSH_CONSTANT_INDEX if no push constant is selected
91+
Uint32 GetPushConstantResourceIndex() const { return m_PushConstantResourceIndex; }
92+
8193
private:
8294
VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
8395

@@ -95,6 +107,12 @@ class PipelineLayoutVk
95107
// Shader stages that use push constants
96108
VkShaderStageFlags m_PushConstantStageFlags = 0;
97109

110+
// Index of the signature containing the push constant resource
111+
Uint32 m_PushConstantSignatureIndex = INVALID_PUSH_CONSTANT_INDEX;
112+
113+
// Resource index within the signature for push constant
114+
Uint32 m_PushConstantResourceIndex = INVALID_PUSH_CONSTANT_INDEX;
115+
98116
#ifdef DILIGENT_DEBUG
99117
Uint32 m_DbgMaxBindIndex = 0;
100118
#endif

Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ enum class DescriptorType : Uint8
6363

6464

6565
// sizeof(PipelineResourceAttribsVk) == 16, x64
66+
// Note: Push constant selection is deferred to PSO creation time.
67+
// At PRS level, all inline constants are treated uniformly with descriptor sets.
6668
struct PipelineResourceAttribsVk
6769
{
6870
private:
@@ -72,9 +74,9 @@ struct PipelineResourceAttribsVk
7274
static constexpr Uint32 _DescrTypeBits = 5;
7375
static constexpr Uint32 _DescrSetBits = 1;
7476
static constexpr Uint32 _SamplerAssignedBits = 1;
75-
static constexpr Uint32 _IsPushConstantBits = 1;
77+
static constexpr Uint32 _ReservedBits = 1; // Reserved for future use
7678

77-
static_assert((_BindingIndexBits + _ArraySizeBits + _SamplerIndBits + _DescrTypeBits + _DescrSetBits + _SamplerAssignedBits + _IsPushConstantBits) % 32 == 0, "Bits are not optimally packed");
79+
static_assert((_BindingIndexBits + _ArraySizeBits + _SamplerIndBits + _DescrTypeBits + _DescrSetBits + _SamplerAssignedBits + _ReservedBits) % 32 == 0, "Bits are not optimally packed");
7880

7981
// clang-format off
8082
static_assert((1u << _DescrTypeBits) > static_cast<Uint32>(DescriptorType::Count), "Not enough bits to store DescriptorType values");
@@ -89,11 +91,11 @@ struct PipelineResourceAttribsVk
8991
// clang-format off
9092
const Uint32 BindingIndex : _BindingIndexBits; // Binding in the descriptor set
9193
const Uint32 SamplerInd : _SamplerIndBits; // Index of the assigned sampler in m_Desc.Resources and m_pPipelineResourceAttribsVk
92-
const Uint32 ArraySize : _ArraySizeBits; // Array size (for push constants, this is the number of 32-bit constants)
94+
const Uint32 ArraySize : _ArraySizeBits; // Array size (for inline constants, this is the number of 32-bit constants)
9395
const Uint32 DescrType : _DescrTypeBits; // Descriptor type (DescriptorType)
9496
const Uint32 DescrSet : _DescrSetBits; // Descriptor set (0 or 1)
9597
const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag
96-
const Uint32 IsPushConstant : _IsPushConstantBits; // True if this is a Vulkan push constant (not using descriptor sets)
98+
const Uint32 Reserved : _ReservedBits; // Reserved for future use
9799

98100
const Uint32 SRBCacheOffset; // Offset in the SRB resource cache
99101
const Uint32 StaticCacheOffset; // Offset in the static resource cache
@@ -105,7 +107,6 @@ struct PipelineResourceAttribsVk
105107
DescriptorType _DescrType,
106108
Uint32 _DescrSet,
107109
bool _ImtblSamplerAssigned,
108-
bool _IsPushConstant,
109110
Uint32 _SRBCacheOffset,
110111
Uint32 _StaticCacheOffset) noexcept :
111112
// clang-format off
@@ -115,7 +116,7 @@ struct PipelineResourceAttribsVk
115116
DescrType {static_cast<Uint32>(_DescrType)},
116117
DescrSet {_DescrSet },
117118
ImtblSamplerAssigned {_ImtblSamplerAssigned ? 1u : 0u},
118-
IsPushConstant {_IsPushConstant ? 1u : 0u },
119+
Reserved {0 },
119120
SRBCacheOffset {_SRBCacheOffset },
120121
StaticCacheOffset {_StaticCacheOffset }
121122
// clang-format on
@@ -131,7 +132,7 @@ struct PipelineResourceAttribsVk
131132

132133
// Only for serialization
133134
PipelineResourceAttribsVk() noexcept :
134-
PipelineResourceAttribsVk{0, 0, 0, DescriptorType::Unknown, 0, false, false, 0, 0}
135+
PipelineResourceAttribsVk{0, 0, 0, DescriptorType::Unknown, 0, false, 0, 0}
135136
{}
136137

137138

@@ -155,11 +156,6 @@ struct PipelineResourceAttribsVk
155156
return SamplerInd != InvalidSamplerInd;
156157
}
157158

158-
bool IsPushConstantBuffer() const
159-
{
160-
return IsPushConstant != 0;
161-
}
162-
163159
bool IsCompatibleWith(const PipelineResourceAttribsVk& rhs) const
164160
{
165161
// Ignore sampler index and cache offsets.
@@ -168,14 +164,13 @@ struct PipelineResourceAttribsVk
168164
ArraySize == rhs.ArraySize &&
169165
DescrType == rhs.DescrType &&
170166
DescrSet == rhs.DescrSet &&
171-
ImtblSamplerAssigned == rhs.ImtblSamplerAssigned &&
172-
IsPushConstant == rhs.IsPushConstant;
167+
ImtblSamplerAssigned == rhs.ImtblSamplerAssigned;
173168
// clang-format on
174169
}
175170

176171
size_t GetHash() const
177172
{
178-
return ComputeHash(BindingIndex, ArraySize, DescrType, DescrSet, ImtblSamplerAssigned, IsPushConstant);
173+
return ComputeHash(BindingIndex, ArraySize, DescrType, DescrSet, ImtblSamplerAssigned);
179174
}
180175
};
181176
ASSERT_SIZEOF(PipelineResourceAttribsVk, 16, "The struct is used in serialization and must be tightly packed");

Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,24 @@ struct ImmutableSamplerAttribsVk
6060
ASSERT_SIZEOF(ImmutableSamplerAttribsVk, 8, "The struct is used in serialization and must be tightly packed");
6161

6262
/// Inline constant buffer attributes for Vulkan backend.
63-
/// Inline constants can be either:
64-
/// 1. True push constants (from SPIR-V push_constant storage class) - use vkCmdPushConstants
65-
/// 2. Emulated inline constants - use dynamic uniform buffers (similar to D3D11 backend)
63+
/// All inline constants are treated uniformly at PRS level - they all get:
64+
/// - DescriptorSet binding and cache allocation
65+
/// - Shared emulated buffer (created in the Signature, shared by all SRBs)
6666
///
67-
/// For emulated inline constants (not push constants), the Buffer is created in the Signature
68-
/// and shared by all SRBs (similar to D3D11). Each SRB has its own CPU staging memory.
69-
/// For push constants, pPushConstantData points to the static cache's staging memory.
67+
/// Push constant selection is deferred to PSO creation time. At PSO creation,
68+
/// one inline constant may be selected to use vkCmdPushConstants based on:
69+
/// 1. SPIR-V reflection (ResourceType::PushConstant in shader)
70+
/// 2. First inline constant as fallback (converted via PatchShader)
7071
struct InlineConstantBufferAttribsVk
7172
{
72-
Uint32 ResIndex = 0; // Resource index in the signature (used for matching)
73-
Uint32 DescrSet = 0; // Descriptor set index (0 for push constants as placeholder)
74-
Uint32 BindingIndex = 0; // Binding index within the descriptor set
75-
Uint32 NumConstants = 0; // Number of 32-bit constants
76-
bool IsPushConstant = false; // True if this is a Vulkan push constant (not emulated)
73+
Uint32 ResIndex = 0; // Resource index in the signature (used for matching)
74+
Uint32 DescrSet = 0; // Descriptor set index
75+
Uint32 BindingIndex = 0; // Binding index within the descriptor set
76+
Uint32 NumConstants = 0; // Number of 32-bit constants
7777

78-
// For emulated inline constants: shared buffer created in the Signature (similar to D3D11)
78+
// Shared buffer created in the Signature (similar to D3D11)
7979
// All SRBs reference this same buffer to reduce memory usage.
8080
RefCntAutoPtr<BufferVkImpl> pBuffer;
81-
82-
// For static push constants: pointer to data in the static resource cache
83-
// This allows CopyStaticResources to copy the data to SRB caches.
84-
void* pPushConstantData = nullptr;
8581
};
8682

8783
struct PipelineResourceSignatureInternalDataVk : PipelineResourceSignatureInternalData<PipelineResourceAttribsVk, ImmutableSamplerAttribsVk>
@@ -161,9 +157,12 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
161157
VkDescriptorSet vkDynamicDescriptorSet) const;
162158

163159
// Updates inline constant buffers by mapping the internal buffers and copying data from the resource cache
164-
// ResourceCache must be valid - each SRB has its own copy of push constant data stored in the cache
160+
// ResourceCache must be valid - each SRB has its own copy of inline constant data stored in the cache
161+
// PushConstantResIndex: Resource index of the inline constant selected as push constant by PSO
162+
// Pass ~0u if no push constant is selected from this signature
165163
void UpdateInlineConstantBuffers(const ShaderResourceCacheVk& ResourceCache,
166-
DeviceContextVkImpl& Ctx) const;
164+
DeviceContextVkImpl& Ctx,
165+
Uint32 PushConstantResIndex) const;
167166

168167
// Returns the number of inline constant buffers
169168
Uint32 GetNumInlineConstantBufferAttribs() const { return m_NumInlineConstantBufferAttribs; }
@@ -236,10 +235,9 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
236235
// Inline constant buffer attributes
237236
std::unique_ptr<InlineConstantBufferAttribsVk[]> m_InlineConstantBufferAttribs;
238237

239-
// Note: Static inline constant data (including push constants) is stored in m_pStaticResCache.
240-
// For push constants, we use InitializePushConstantDataPtrs() and SetPushConstantDataPtr()
241-
// in the static resource cache, similar to how SRB caches store push constant data.
242-
// This ensures each SRB gets its own copy when CopyStaticResources() is called.
238+
// Note: Static inline constant data is stored in m_pStaticResCache.
239+
// Push constant selection is deferred to PSO creation time - the PRS treats
240+
// all inline constants uniformly with emulated buffers.
243241
};
244242

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

Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,11 @@ class PipelineStateVkImpl final : public PipelineStateBase<EngineVkImplTraits>
133133
void InitializePipeline(const ComputePipelineStateCreateInfo& CreateInfo);
134134
void InitializePipeline(const RayTracingPipelineStateCreateInfo& CreateInfo);
135135

136-
void InitPushConstantInfoFromSignatures(PushConstantInfoVk& PushConstant) const noexcept(false);
136+
bool InitPushConstantInfoFromSignatures(PushConstantInfoVk& PushConstant,
137+
TShaderStages& ShaderStages) const noexcept(false);
137138

138-
void PatchShaderConvertUniformBufferToPushConstant(TShaderStages& ShaderStages) const noexcept(false);
139+
void PatchShaderConvertUniformBufferToPushConstant(TShaderStages& ShaderStages,
140+
const PushConstantInfoVk& PushConstant) const noexcept(false);
139141

140142
// TPipelineStateBase::Construct needs access to InitializePipeline
141143
friend TPipelineStateBase;

0 commit comments

Comments
 (0)