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};
705705DEFINE_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
709787struct 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