Skip to content

Commit 12c9176

Browse files
committed
Add SpecializationConstant declaration to PipelineState.
1 parent 163fb0c commit 12c9176

1 file changed

Lines changed: 111 additions & 4 deletions

File tree

Graphics/GraphicsEngine/interface/PipelineState.h

Lines changed: 111 additions & 4 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");
@@ -704,6 +704,84 @@ DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32)
704704
};
705705
DEFINE_FLAG_ENUM_OPERATORS(PSO_CREATE_FLAGS);
706706

707+
/// Specialization constants allow applications to set constant values
708+
/// at pipeline creation time, enabling the driver to optimize the compiled
709+
/// shader code.
710+
///
711+
/// \remarks Specialization constants are supported in Vulkan (via VkSpecializationInfo)
712+
/// and WebGPU (via pipeline-overridable constants). Other backends
713+
/// will reject non-empty specialization constants.
714+
struct SpecializationConstant
715+
{
716+
/// Specialization constant name as defined in the shader source.
717+
718+
/// In GLSL/SPIR-V, this corresponds to the name decorated with the
719+
/// `constant_id` layout qualifier.
720+
/// In WGSL, this corresponds to the name of an `override` declaration.
721+
///
722+
/// Must not be null.
723+
const Char* Name DEFAULT_INITIALIZER(nullptr);
724+
725+
/// Shader stages this specialization constant applies to.
726+
727+
/// Specifies which shader stages use this constant.
728+
/// The value must be a valid combination of SHADER_TYPE flags.
729+
SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
730+
731+
/// Size of the specialization constant data, in bytes.
732+
733+
/// Must match the size of the constant's type as declared in the shader.
734+
Uint32 Size DEFAULT_INITIALIZER(0);
735+
736+
/// Pointer to the specialization constant data.
737+
738+
/// The data is interpreted as raw bytes and must be at least
739+
/// `Size` bytes long. Must not be null when Size > 0.
740+
const void* pData DEFAULT_INITIALIZER(nullptr);
741+
742+
#if DILIGENT_CPP_INTERFACE
743+
constexpr SpecializationConstant() noexcept {}
744+
745+
constexpr SpecializationConstant(const Char* _Name,
746+
SHADER_TYPE _ShaderStages,
747+
Uint32 _Size,
748+
const void* _pData) noexcept :
749+
Name {_Name },
750+
ShaderStages{_ShaderStages},
751+
Size {_Size },
752+
pData {_pData }
753+
{}
754+
755+
bool operator==(const SpecializationConstant& RHS) const noexcept
756+
{
757+
if (ShaderStages != RHS.ShaderStages ||
758+
Size != RHS.Size ||
759+
!SafeStrEqual(Name, RHS.Name))
760+
return false;
761+
762+
if (pData != RHS.pData)
763+
{
764+
if (Size == 0)
765+
return true;
766+
767+
if ((pData == nullptr) != (RHS.pData == nullptr))
768+
return false;
769+
770+
if (pData != nullptr && memcmp(pData, RHS.pData, Size) != 0)
771+
return false;
772+
}
773+
774+
return true;
775+
}
776+
777+
bool operator!=(const SpecializationConstant& RHS) const noexcept
778+
{
779+
return !(*this == RHS);
780+
}
781+
#endif
782+
};
783+
typedef struct SpecializationConstant SpecializationConstant;
784+
707785

708786
/// Pipeline state creation attributes
709787
struct PipelineStateCreateInfo
@@ -729,6 +807,22 @@ struct PipelineStateCreateInfo
729807
/// should be in it default state.
730808
IPipelineResourceSignature** ppResourceSignatures DEFAULT_INITIALIZER(nullptr);
731809

810+
/// The number of specialization constants.
811+
Uint32 NumSpecializationConstants DEFAULT_INITIALIZER(0);
812+
813+
/// Pointer to an array of NumSpecializationConstants SpecializationConstant
814+
/// elements that define the values of specialization constants for the pipeline.
815+
816+
/// Specialization constants allow applications to set constant values at pipeline
817+
/// creation time, enabling the driver to optimize the compiled shader code.
818+
///
819+
/// This feature requires DeviceFeatures.SpecializationConstants to be enabled.
820+
/// If the device does not support specialization constants, non-empty arrays
821+
/// will be rejected during pipeline creation.
822+
///
823+
/// \sa SpecializationConstant
824+
const SpecializationConstant* pSpecializationConstants DEFAULT_INITIALIZER(nullptr);
825+
732826
/// Optional pipeline state cache that is used to accelerate
733827
/// PSO creation. If `PSODesc.Name` is found in the cache, the cache
734828
/// data is used to create the PSO. Otherwise, the PSO
@@ -751,9 +845,10 @@ struct PipelineStateCreateInfo
751845

752846
bool operator==(const PipelineStateCreateInfo& RHS) const noexcept
753847
{
754-
if (PSODesc != RHS.PSODesc ||
755-
Flags != RHS.Flags ||
756-
ResourceSignaturesCount != RHS.ResourceSignaturesCount)
848+
if (PSODesc != RHS.PSODesc ||
849+
Flags != RHS.Flags ||
850+
ResourceSignaturesCount != RHS.ResourceSignaturesCount ||
851+
NumSpecializationConstants != RHS.NumSpecializationConstants)
757852
return false;
758853

759854
if (ppResourceSignatures != RHS.ppResourceSignatures)
@@ -776,6 +871,18 @@ struct PipelineStateCreateInfo
776871
}
777872
}
778873

874+
if (pSpecializationConstants != RHS.pSpecializationConstants)
875+
{
876+
if ((pSpecializationConstants == nullptr) != (RHS.pSpecializationConstants == nullptr))
877+
return false;
878+
879+
for (Uint32 i = 0; i < NumSpecializationConstants; ++i)
880+
{
881+
if (pSpecializationConstants[i] != RHS.pSpecializationConstants[i])
882+
return false;
883+
}
884+
}
885+
779886
// Ignore PSO cache and pInternalData
780887

781888
return true;

0 commit comments

Comments
 (0)