godot/thirdparty/spirv-reflect/patches/specialization-constants.patch

293 lines
12 KiB
Diff

diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
index d41b30874e..a830ca9ebf 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
@@ -136,6 +136,9 @@ typedef struct SpvReflectPrvDecorations {
SpvReflectPrvNumberDecoration component;
SpvReflectPrvNumberDecoration offset;
SpvReflectPrvNumberDecoration uav_counter_buffer;
+// -- GODOT begin --
+ SpvReflectPrvNumberDecoration specialization_constant;
+// -- GODOT end --
SpvReflectPrvStringDecoration semantic;
uint32_t array_stride;
uint32_t matrix_stride;
@@ -730,6 +733,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* 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;
@@ -944,7 +950,15 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
case SpvOpSpecConstantTrue:
case SpvOpSpecConstantFalse:
- case SpvOpSpecConstant:
+// -- GODOT begin --
+ 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);
@@ -1464,6 +1478,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
skip = true;
}
break;
+// -- GODOT begin --
+ case SpvDecorationSpecId:
+// -- GODOT end --
case SpvDecorationRelaxedPrecision:
case SpvDecorationBlock:
case SpvDecorationBufferBlock:
@@ -1622,6 +1639,15 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
}
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);
@@ -1955,6 +1981,14 @@ 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) {
@@ -3650,6 +3684,69 @@ static SpvReflectResult ParseExecutionModes(
return SPV_REFLECT_RESULT_SUCCESS;
}
+// -- GODOT begin --
+static SpvReflectResult ParseSpecializationConstants(SpvReflectPrvParser* 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) {
+ SpvReflectPrvNode* 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) {
+ SpvReflectPrvNode* 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);
+
+ SpvReflectPrvNode* 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(
SpvReflectPrvParser* p_parser,
SpvReflectShaderModule* p_module)
@@ -4070,6 +4167,12 @@ static SpvReflectResult CreateShaderModule(
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);
@@ -4233,6 +4336,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
}
SafeFree(p_module->capabilities);
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) {
@@ -4503,6 +4609,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 12ef2b1e3e..759db682f4 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
@@ -359,6 +359,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
@brief The OpVariable that is either an Input or Output to the module
@@ -530,6 +552,10 @@ typedef struct SpvReflectShaderModule {
SpvReflectInterfaceVariable* interface_variables; // Uses value(s) from first entry point
uint32_t push_constant_block_count; // Uses value(s) from first entry point
SpvReflectBlockVariable* push_constant_blocks; // Uses value(s) from first entry point
+ // -- GODOT begin --
+ uint32_t specialization_constant_count;
+ SpvReflectSpecializationConstant* specialization_constants;
+ // -- GODOT end --
struct Internal {
SpvReflectModuleFlags module_flags;
@@ -802,6 +828,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.