@@ -225,6 +225,7 @@ typedef struct SpvReflectPrvParser {
225225 uint32_t type_count ;
226226 uint32_t descriptor_count ;
227227 uint32_t push_constant_count ;
228+ uint32_t spec_constant_count ;
228229
229230 SpvReflectTypeDescription * physical_pointer_check [MAX_RECURSIVE_PHYSICAL_POINTER_CHECK ];
230231 uint32_t physical_pointer_count ;
@@ -1420,7 +1421,7 @@ static bool UserTypeMatches(const char* user_type, const char* pattern) {
14201421 return false;
14211422}
14221423
1423- static SpvReflectResult ParseDecorations (SpvReflectPrvParser * p_parser , SpvReflectShaderModule * p_module ) {
1424+ static SpvReflectResult ParseDecorations (SpvReflectPrvParser * p_parser ) {
14241425 uint32_t spec_constant_count = 0 ;
14251426 for (uint32_t i = 0 ; i < p_parser -> node_count ; ++ i ) {
14261427 SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
@@ -1722,31 +1723,7 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser, SpvRefle
17221723 }
17231724 }
17241725
1725- if (spec_constant_count > 0 ) {
1726- p_module -> spec_constants = (SpvReflectSpecializationConstant * )calloc (spec_constant_count , sizeof (* p_module -> spec_constants ));
1727- if (IsNull (p_module -> spec_constants )) {
1728- return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
1729- }
1730- }
1731- for (uint32_t i = 0 ; i < p_parser -> node_count ; ++ i ) {
1732- SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
1733- if (p_node -> op == SpvOpDecorate ) {
1734- uint32_t decoration = (uint32_t )INVALID_VALUE ;
1735- CHECKED_READU32 (p_parser , p_node -> word_offset + 2 , decoration );
1736- if (decoration == SpvDecorationSpecId ) {
1737- const uint32_t count = p_module -> spec_constant_count ;
1738- CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , p_module -> spec_constants [count ].spirv_id );
1739- CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , p_module -> spec_constants [count ].constant_id );
1740- // If being used for a OpSpecConstantComposite (ex. LocalSizeId), there won't be a name
1741- SpvReflectPrvNode * target_node = FindNode (p_parser , p_module -> spec_constants [count ].spirv_id );
1742- if (IsNotNull (target_node )) {
1743- p_module -> spec_constants [count ].name = target_node -> name ;
1744- }
1745- p_module -> spec_constant_count ++ ;
1746- }
1747- }
1748- }
1749-
1726+ p_parser -> spec_constant_count = spec_constant_count ;
17501727 return SPV_REFLECT_RESULT_SUCCESS ;
17511728}
17521729
@@ -4055,6 +4032,63 @@ static SpvReflectResult ParsePushConstantBlocks(SpvReflectPrvParser* p_parser, S
40554032 return SPV_REFLECT_RESULT_SUCCESS ;
40564033}
40574034
4035+ static SpvReflectResult ParseSpecConstants (SpvReflectPrvParser * p_parser , SpvReflectShaderModule * p_module ) {
4036+ if (p_parser -> spec_constant_count > 0 ) {
4037+ p_module -> spec_constants = (SpvReflectSpecializationConstant * )calloc (p_parser -> spec_constant_count , sizeof (* p_module -> spec_constants ));
4038+ if (IsNull (p_module -> spec_constants )) {
4039+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED ;
4040+ }
4041+ } else {
4042+ return SPV_REFLECT_RESULT_SUCCESS ;
4043+ }
4044+ for (uint32_t i = 0 ; i < p_parser -> node_count ; ++ i ) {
4045+ SpvReflectPrvNode * p_node = & (p_parser -> nodes [i ]);
4046+ if (p_node -> op == SpvOpDecorate ) {
4047+ uint32_t decoration = (uint32_t )INVALID_VALUE ;
4048+ CHECKED_READU32 (p_parser , p_node -> word_offset + 2 , decoration );
4049+ if (decoration == SpvDecorationSpecId ) {
4050+ SpvReflectSpecializationConstant * p_spec_constant = & (p_module -> spec_constants [p_module -> spec_constant_count ]);
4051+ CHECKED_READU32 (p_parser , p_node -> word_offset + 1 , p_spec_constant -> spirv_id );
4052+ CHECKED_READU32 (p_parser , p_node -> word_offset + 3 , p_spec_constant -> constant_id );
4053+ SpvReflectPrvNode * target_node = FindNode (p_parser , p_spec_constant -> spirv_id );
4054+ if (IsNotNull (target_node )) {
4055+ // If being used for a OpSpecConstantComposite (ex. LocalSizeId), there won't be a name
4056+ p_spec_constant -> name = target_node -> name ;
4057+
4058+ // During external specialization, Boolean values are true if non-zero and false if zero.
4059+ static uint32_t true_value = 1 ;
4060+ static uint32_t false_value = 0 ;
4061+ switch (target_node -> op ) {
4062+ default :
4063+ // Unexpected, since Spec states:
4064+ // (SpecId) Apply only to a scalar specialization constant
4065+ SPV_REFLECT_ASSERT (false);
4066+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION ;
4067+ case SpvOpSpecConstantTrue :
4068+ p_spec_constant -> default_value_size = sizeof (uint32_t );
4069+ p_spec_constant -> default_value = & true_value ;
4070+ break ;
4071+ case SpvOpSpecConstantFalse :
4072+ p_spec_constant -> default_value_size = sizeof (uint32_t );
4073+ p_spec_constant -> default_value = & false_value ;
4074+ break ;
4075+ case SpvOpSpecConstant :
4076+ p_spec_constant -> default_value_size = (target_node -> word_count - 3 ) * sizeof (uint32_t );
4077+ p_spec_constant -> default_value = p_parser -> spirv_code + target_node -> word_offset + 3 ;
4078+ break ;
4079+ }
4080+ p_spec_constant -> type_description = FindType (p_module , target_node -> result_type_id );
4081+ } else {
4082+ // Decoration target not found
4083+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE ;
4084+ }
4085+ p_module -> spec_constant_count ++ ;
4086+ }
4087+ }
4088+ }
4089+ return SPV_REFLECT_RESULT_SUCCESS ;
4090+ }
4091+
40584092static int SortCompareDescriptorSet (const void * a , const void * b ) {
40594093 const SpvReflectDescriptorSet * p_elem_a = (const SpvReflectDescriptorSet * )a ;
40604094 const SpvReflectDescriptorSet * p_elem_b = (const SpvReflectDescriptorSet * )b ;
@@ -4307,7 +4341,7 @@ static SpvReflectResult CreateShaderModule(uint32_t flags, size_t size, const vo
43074341 SPV_REFLECT_ASSERT (result == SPV_REFLECT_RESULT_SUCCESS );
43084342 }
43094343 if (result == SPV_REFLECT_RESULT_SUCCESS ) {
4310- result = ParseDecorations (& parser , p_module );
4344+ result = ParseDecorations (& parser );
43114345 SPV_REFLECT_ASSERT (result == SPV_REFLECT_RESULT_SUCCESS );
43124346 }
43134347
@@ -4348,6 +4382,10 @@ static SpvReflectResult CreateShaderModule(uint32_t flags, size_t size, const vo
43484382 result = ParsePushConstantBlocks (& parser , p_module );
43494383 SPV_REFLECT_ASSERT (result == SPV_REFLECT_RESULT_SUCCESS );
43504384 }
4385+ if (result == SPV_REFLECT_RESULT_SUCCESS ) {
4386+ result = ParseSpecConstants (& parser , p_module );
4387+ SPV_REFLECT_ASSERT (result == SPV_REFLECT_RESULT_SUCCESS );
4388+ }
43514389 if (result == SPV_REFLECT_RESULT_SUCCESS ) {
43524390 result = ParseEntryPoints (& parser , p_module );
43534391 SPV_REFLECT_ASSERT (result == SPV_REFLECT_RESULT_SUCCESS );
0 commit comments