Skip to content

Commit 02e825e

Browse files
committed
Add type description and default value to specialization constants
1 parent 3d8968e commit 02e825e

File tree

2 files changed

+78
-27
lines changed

2 files changed

+78
-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+
switch (target_node->op) {
4058+
default:
4059+
// Unexpected, since Spec states:
4060+
// (SpecId) Apply only to a scalar specialization constant
4061+
SPV_REFLECT_ASSERT(false);
4062+
return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION;
4063+
case SpvOpSpecConstantTrue:
4064+
// During external specialization, Boolean values are true if non-zero.
4065+
static uint32_t true_value = 1;
4066+
p_spec_constant->size = sizeof(uint32_t);
4067+
p_spec_constant->default_value = &true_value;
4068+
break;
4069+
case SpvOpSpecConstantFalse:
4070+
// During external specialization, Boolean values are false if zero.
4071+
static uint32_t false_value = 0;
4072+
p_spec_constant->size = sizeof(uint32_t);
4073+
p_spec_constant->default_value = &false_value;
4074+
break;
4075+
case SpvOpSpecConstant:
4076+
p_spec_constant->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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,19 @@ 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+
uint32_t size;
587+
588+
// Pointer to the raw default value data.
589+
// The interpretation of this data depends on type_description->op:
590+
// - SpvOpSpecConstantTrue: size = 4, data = uint32_t(1)
591+
// - SpvOpSpecConstantFalse: size = 4, data = uint32_t(0)
592+
// - SpvOpSpecConstant: data contains the bit pattern of the default value
593+
// * Types 32 bits wide or smaller take one word.
594+
// * Larger types take multiple words, with low-order words appearing first.
595+
void* default_value;
583596
} SpvReflectSpecializationConstant;
584597

585598
/*! @struct SpvReflectShaderModule

0 commit comments

Comments
 (0)