diff options
author | reduz <reduzio@gmail.com> | 2021-07-09 16:48:28 -0300 |
---|---|---|
committer | RĂ©mi Verschelde <rverschelde@gmail.com> | 2021-07-11 23:16:09 +0200 |
commit | b2f6db7aa817159bd57d88bff8af017a89759aab (patch) | |
tree | 26b3401a34ee165adb9c41bdf63c6f6fc90cb0d6 /thirdparty/spirv-reflect | |
parent | fb3961b2ef9ed03501f98a8aa621f78679cc2be9 (diff) |
Implement Specialization Constants
* Added support to our local copy of SpirV Reflect (which does not support it).
* Pass them on render or compute pipeline creation.
* Not implemented in our shaders yet.
Diffstat (limited to 'thirdparty/spirv-reflect')
-rw-r--r-- | thirdparty/spirv-reflect/patches/specialization-constants.patch | 293 | ||||
-rw-r--r-- | thirdparty/spirv-reflect/spirv_reflect.c | 139 | ||||
-rw-r--r-- | thirdparty/spirv-reflect/spirv_reflect.h | 53 |
3 files changed, 482 insertions, 3 deletions
diff --git a/thirdparty/spirv-reflect/patches/specialization-constants.patch b/thirdparty/spirv-reflect/patches/specialization-constants.patch new file mode 100644 index 0000000000..8ff1dcc2e5 --- /dev/null +++ b/thirdparty/spirv-reflect/patches/specialization-constants.patch @@ -0,0 +1,293 @@ +diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c +index 0fc979a8a4..3e3643717a 100644 +--- a/thirdparty/spirv-reflect/spirv_reflect.c ++++ b/thirdparty/spirv-reflect/spirv_reflect.c +@@ -124,6 +124,9 @@ typedef struct Decorations { + NumberDecoration location; + NumberDecoration offset; + NumberDecoration uav_counter_buffer; ++// -- GODOT begin -- ++ NumberDecoration specialization_constant; ++// -- GODOT end -- + StringDecoration semantic; + uint32_t array_stride; + uint32_t matrix_stride; +@@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser) + p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE; ++// -- GODOT begin -- ++ p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE; ++// -- GODOT end -- + } + // Mark source file id node + p_parser->source_file_id = (uint32_t)INVALID_VALUE; +@@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser) + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } + break; +- ++// -- GODOT begin -- + case SpvOpSpecConstantTrue: + case SpvOpSpecConstantFalse: +- case SpvOpSpecConstant: ++ case SpvOpSpecConstant: { ++ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); ++ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); ++ p_node->is_type = true; ++ } ++ break; ++// -- GODOT end -- + case SpvOpSpecConstantComposite: + case SpvOpSpecConstantOp: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); +@@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser) + skip = true; + } + break; ++// -- GODOT begin -- ++ case SpvDecorationSpecId: ++// -- GODOT end -- + case SpvDecorationBlock: + case SpvDecorationBufferBlock: + case SpvDecorationColMajor: +@@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser) + p_target_decorations->input_attachment_index.word_offset = word_offset; + } + break; +- ++// -- GODOT begin -- ++ case SpvDecorationSpecId: { ++ uint32_t word_offset = p_node->word_offset + member_offset+ 3; ++ CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value); ++ p_target_decorations->specialization_constant.word_offset = word_offset; ++ } ++ break; ++// -- GODOT end -- + case SpvReflectDecorationHlslCounterBufferGOOGLE: { + uint32_t word_offset = p_node->word_offset + member_offset+ 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value); +@@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType( + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE; + } + break; ++// -- GODOT begin -- ++ case SpvOpSpecConstantTrue: ++ case SpvOpSpecConstantFalse: ++ case SpvOpSpecConstant: { ++ } ++ break; ++// -- GODOT end -- + } + + if (result == SPV_REFLECT_RESULT_SUCCESS) { +@@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo + return SPV_REFLECT_RESULT_SUCCESS; + } + ++// -- GODOT begin -- ++static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module) ++{ ++ p_module->specialization_constant_count = 0; ++ p_module->specialization_constants = NULL; ++ for (size_t i = 0; i < p_parser->node_count; ++i) { ++ Node* p_node = &(p_parser->nodes[i]); ++ if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) { ++ p_module->specialization_constant_count++; ++ } ++ } ++ ++ if (p_module->specialization_constant_count == 0) { ++ return SPV_REFLECT_RESULT_SUCCESS; ++ } ++ ++ p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant)); ++ ++ uint32_t index = 0; ++ ++ for (size_t i = 0; i < p_parser->node_count; ++i) { ++ Node* p_node = &(p_parser->nodes[i]); ++ switch(p_node->op) { ++ default: continue; ++ case SpvOpSpecConstantTrue: { ++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL; ++ p_module->specialization_constants[index].default_value.int_bool_value = 1; ++ } break; ++ case SpvOpSpecConstantFalse: { ++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL; ++ p_module->specialization_constants[index].default_value.int_bool_value = 0; ++ } break; ++ case SpvOpSpecConstant: { ++ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; ++ uint32_t element_type_id = (uint32_t)INVALID_VALUE; ++ uint32_t default_value = 0; ++ IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id); ++ IF_READU32(result, p_parser, p_node->word_offset + 3, default_value); ++ ++ Node* p_next_node = FindNode(p_parser, element_type_id); ++ ++ if (p_next_node->op == SpvOpTypeInt) { ++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT; ++ } else if (p_next_node->op == SpvOpTypeFloat) { ++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT; ++ } else { ++ return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED; ++ } ++ ++ p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float ++ } break; ++ } ++ ++ p_module->specialization_constants[index].name = p_node->name; ++ p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value; ++ p_module->specialization_constants[index].spirv_id = p_node->result_id; ++ index++; ++ } ++ ++ return SPV_REFLECT_RESULT_SUCCESS; ++} ++// -- GODOT end -- ++ + static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module) + { + for (size_t i = 0; i < p_parser->node_count; ++i) { +@@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule( + result = ParsePushConstantBlocks(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } ++// -- GODOT begin -- ++ if (result == SPV_REFLECT_RESULT_SUCCESS) { ++ result = ParseSpecializationConstants(&parser, p_module); ++ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); ++ } ++// -- GODOT end -- + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseEntryPoints(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); +@@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) + SafeFree(p_entry->used_push_constants); + } + SafeFree(p_module->entry_points); ++// -- GODOT begin -- ++ SafeFree(p_module->specialization_constants); ++// -- GODOT end -- + + // Push constants + for (size_t i = 0; i < p_module->push_constant_block_count; ++i) { +@@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( + return SPV_REFLECT_RESULT_SUCCESS; + } + ++// -- GODOT begin -- ++SpvReflectResult spvReflectEnumerateSpecializationConstants( ++ const SpvReflectShaderModule* p_module, ++ uint32_t* p_count, ++ SpvReflectSpecializationConstant** pp_constants ++) ++{ ++ if (IsNull(p_module)) { ++ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; ++ } ++ if (IsNull(p_count)) { ++ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; ++ } ++ ++ if (IsNotNull(pp_constants)) { ++ if (*p_count != p_module->specialization_constant_count) { ++ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; ++ } ++ ++ for (uint32_t index = 0; index < *p_count; ++index) { ++ SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index]; ++ pp_constants[index] = p_const; ++ } ++ } ++ else { ++ *p_count = p_module->specialization_constant_count; ++ } ++ ++ return SPV_REFLECT_RESULT_SUCCESS; ++} ++// -- GODOT end -- ++ + SpvReflectResult spvReflectEnumerateInputVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, +diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h +index a5a956e9e8..21f8160770 100644 +--- a/thirdparty/spirv-reflect/spirv_reflect.h ++++ b/thirdparty/spirv-reflect/spirv_reflect.h +@@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription { + struct SpvReflectTypeDescription* members; + } SpvReflectTypeDescription; + ++// -- GODOT begin -- ++/*! @struct SpvReflectSpecializationConstant ++ ++*/ ++ ++typedef enum SpvReflectSpecializationConstantType { ++ SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0, ++ SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1, ++ SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2, ++} SpvReflectSpecializationConstantType; ++ ++typedef struct SpvReflectSpecializationConstant { ++ const char* name; ++ uint32_t spirv_id; ++ uint32_t constant_id; ++ SpvReflectSpecializationConstantType constant_type; ++ union { ++ float float_value; ++ uint32_t int_bool_value; ++ } default_value; ++} SpvReflectSpecializationConstant; ++// -- GODOT end -- + + /*! @struct SpvReflectInterfaceVariable + +@@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule { + SpvReflectInterfaceVariable* interface_variables; + uint32_t push_constant_block_count; + SpvReflectBlockVariable* push_constant_blocks; ++ // -- GODOT begin -- ++ uint32_t specialization_constant_count; ++ SpvReflectSpecializationConstant* specialization_constants; ++ // -- GODOT end -- + + struct Internal { + size_t spirv_size; +@@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables( + SpvReflectInterfaceVariable** pp_variables + ); + ++// -- GOODT begin -- ++/*! @fn spvReflectEnumerateSpecializationConstants ++ @brief If the module contains multiple entry points, this will only get ++ the specialization constants for the first one. ++ @param p_module Pointer to an instance of SpvReflectShaderModule. ++ @param p_count If pp_constants is NULL, the module's specialization constant ++ count will be stored here. ++ If pp_variables is not NULL, *p_count must contain ++ the module's specialization constant count. ++ @param pp_variables If NULL, the module's specialization constant count will be ++ written to *p_count. ++ If non-NULL, pp_constants must point to an array with ++ *p_count entries, where pointers to the module's ++ specialization constants will be written. The caller must not ++ free the specialization constants written to this array. ++ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. ++ Otherwise, the error code indicates the cause of the ++ failure. ++ ++*/ ++SpvReflectResult spvReflectEnumerateSpecializationConstants( ++ const SpvReflectShaderModule* p_module, ++ uint32_t* p_count, ++ SpvReflectSpecializationConstant** pp_constants ++); ++// -- GODOT end -- ++ + /*! @fn spvReflectEnumerateEntryPointInputVariables + @brief Enumerate the input variables for a given entry point. + @param entry_point The name of the entry point to get the input variables for. diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c index 0fc979a8a4..8f614c8874 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c @@ -124,6 +124,9 @@ typedef struct Decorations { NumberDecoration location; NumberDecoration offset; NumberDecoration uav_counter_buffer; +// -- GODOT begin -- + NumberDecoration specialization_constant; +// -- GODOT end -- StringDecoration semantic; uint32_t array_stride; uint32_t matrix_stride; @@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser) p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE; p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE; p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE; +// -- GODOT begin -- + p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE; +// -- GODOT end -- } // Mark source file id node p_parser->source_file_id = (uint32_t)INVALID_VALUE; @@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser) CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); } break; - +// -- GODOT begin -- case SpvOpSpecConstantTrue: case SpvOpSpecConstantFalse: - case SpvOpSpecConstant: + case SpvOpSpecConstant: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + p_node->is_type = true; + } + break; +// -- GODOT end -- case SpvOpSpecConstantComposite: case SpvOpSpecConstantOp: { CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); @@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser) skip = true; } break; +// -- GODOT begin -- + case SpvDecorationSpecId: +// -- GODOT end -- case SpvDecorationBlock: case SpvDecorationBufferBlock: case SpvDecorationColMajor: @@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser) p_target_decorations->input_attachment_index.word_offset = word_offset; } break; - +// -- GODOT begin -- + case SpvDecorationSpecId: { + uint32_t word_offset = p_node->word_offset + member_offset+ 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value); + p_target_decorations->specialization_constant.word_offset = word_offset; + } + break; +// -- GODOT end -- case SpvReflectDecorationHlslCounterBufferGOOGLE: { uint32_t word_offset = p_node->word_offset + member_offset+ 3; CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value); @@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType( p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE; } break; +// -- GODOT begin -- + case SpvOpSpecConstantTrue: + case SpvOpSpecConstantFalse: + case SpvOpSpecConstant: { + } + break; +// -- GODOT end -- } if (result == SPV_REFLECT_RESULT_SUCCESS) { @@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo return SPV_REFLECT_RESULT_SUCCESS; } +// -- GODOT begin -- +static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module) +{ + p_module->specialization_constant_count = 0; + p_module->specialization_constants = NULL; + for (size_t i = 0; i < p_parser->node_count; ++i) { + Node* p_node = &(p_parser->nodes[i]); + if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) { + p_module->specialization_constant_count++; + } + } + + if (p_module->specialization_constant_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant)); + + uint32_t index = 0; + + for (size_t i = 0; i < p_parser->node_count; ++i) { + Node* p_node = &(p_parser->nodes[i]); + switch(p_node->op) { + default: continue; + case SpvOpSpecConstantTrue: { + p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL; + p_module->specialization_constants[index].default_value.int_bool_value = 1; + } break; + case SpvOpSpecConstantFalse: { + p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL; + p_module->specialization_constants[index].default_value.int_bool_value = 0; + } break; + case SpvOpSpecConstant: { + SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; + uint32_t element_type_id = (uint32_t)INVALID_VALUE; + uint32_t default_value = 0; + IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id); + IF_READU32(result, p_parser, p_node->word_offset + 3, default_value); + + Node* p_next_node = FindNode(p_parser, element_type_id); + + if (p_next_node->op == SpvOpTypeInt) { + p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT; + } else if (p_next_node->op == SpvOpTypeFloat) { + p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT; + } else { + return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED; + } + + p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float + } break; + } + + p_module->specialization_constants[index].name = p_node->name; + p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value; + p_module->specialization_constants[index].spirv_id = p_node->result_id; + index++; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} +// -- GODOT end -- + static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module) { for (size_t i = 0; i < p_parser->node_count; ++i) { @@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule( result = ParsePushConstantBlocks(&parser, p_module); SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } +// -- GODOT begin -- + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseSpecializationConstants(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } +// -- GODOT end -- if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseEntryPoints(&parser, p_module); SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); @@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) SafeFree(p_entry->used_push_constants); } SafeFree(p_module->entry_points); +// -- GODOT begin -- + SafeFree(p_module->specialization_constants); +// -- GODOT end -- // Push constants for (size_t i = 0; i < p_module->push_constant_block_count; ++i) { @@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( return SPV_REFLECT_RESULT_SUCCESS; } +// -- GODOT begin -- +SpvReflectResult spvReflectEnumerateSpecializationConstants( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectSpecializationConstant** pp_constants +) +{ + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_constants)) { + if (*p_count != p_module->specialization_constant_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index]; + pp_constants[index] = p_const; + } + } + else { + *p_count = p_module->specialization_constant_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} +// -- GODOT end -- + SpvReflectResult spvReflectEnumerateInputVariables( const SpvReflectShaderModule* p_module, uint32_t* p_count, diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h index a5a956e9e8..21f8160770 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.h +++ b/thirdparty/spirv-reflect/spirv_reflect.h @@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription { struct SpvReflectTypeDescription* members; } SpvReflectTypeDescription; +// -- GODOT begin -- +/*! @struct SpvReflectSpecializationConstant + +*/ + +typedef enum SpvReflectSpecializationConstantType { + SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0, + SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1, + SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2, +} SpvReflectSpecializationConstantType; + +typedef struct SpvReflectSpecializationConstant { + const char* name; + uint32_t spirv_id; + uint32_t constant_id; + SpvReflectSpecializationConstantType constant_type; + union { + float float_value; + uint32_t int_bool_value; + } default_value; +} SpvReflectSpecializationConstant; +// -- GODOT end -- /*! @struct SpvReflectInterfaceVariable @@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule { SpvReflectInterfaceVariable* interface_variables; uint32_t push_constant_block_count; SpvReflectBlockVariable* push_constant_blocks; + // -- GODOT begin -- + uint32_t specialization_constant_count; + SpvReflectSpecializationConstant* specialization_constants; + // -- GODOT end -- struct Internal { size_t spirv_size; @@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables( SpvReflectInterfaceVariable** pp_variables ); +// -- GOODT begin -- +/*! @fn spvReflectEnumerateSpecializationConstants + @brief If the module contains multiple entry points, this will only get + the specialization constants for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_constants is NULL, the module's specialization constant + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the module's specialization constant count. + @param pp_variables If NULL, the module's specialization constant count will be + written to *p_count. + If non-NULL, pp_constants must point to an array with + *p_count entries, where pointers to the module's + specialization constants will be written. The caller must not + free the specialization constants written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateSpecializationConstants( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectSpecializationConstant** pp_constants +); +// -- GODOT end -- + /*! @fn spvReflectEnumerateEntryPointInputVariables @brief Enumerate the input variables for a given entry point. @param entry_point The name of the entry point to get the input variables for. |