Skip to content

Commit ef913b3

Browse files
jjyyxxspencer-lunarg
authored andcommitted
Add type description and default value to specialization constants
1 parent 3d8968e commit ef913b3

File tree

2 files changed

+80
-27
lines changed

2 files changed

+80
-27
lines changed

spirv_reflect.c

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
40584092
static 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);

spirv_reflect.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,21 @@ typedef struct SpvReflectSpecializationConstant {
580580
uint32_t spirv_id;
581581
uint32_t constant_id;
582582
const char* name;
583+
SpvReflectTypeDescription* type_description;
584+
585+
// Size of the default value in bytes (always a multiple of 4).
586+
// Will be 4 for 8/16/32-bit constants and 8 for 64-bit constants.
587+
uint32_t default_value_size;
588+
589+
// Pointer to the raw default value data.
590+
// The interpretation of this data depends on type_description->op:
591+
// - SpvOpSpecConstantTrue: size = 4, data = uint32_t(1)
592+
// - SpvOpSpecConstantFalse: size = 4, data = uint32_t(0)
593+
// - SpvOpSpecConstant: data contains the bit pattern of the default value
594+
// * The type will be a scalar integer or float.
595+
// * Types 32 bits wide or smaller take one word.
596+
// * Larger types take multiple words, with low-order words appearing first.
597+
void* default_value;
583598
} SpvReflectSpecializationConstant;
584599

585600
/*! @struct SpvReflectShaderModule

0 commit comments

Comments
 (0)