|
| 1 | +diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c |
| 2 | +index cca1f68fda..a415afcc67 100644 |
| 3 | +--- a/thirdparty/spirv-reflect/spirv_reflect.c |
| 4 | ++++ b/thirdparty/spirv-reflect/spirv_reflect.c |
| 5 | +@@ -215,6 +215,10 @@ typedef struct SpvReflectPrvParser { |
| 6 | + const char* source_embedded; |
| 7 | + size_t node_count; |
| 8 | + SpvReflectPrvNode* nodes; |
| 9 | ++ // Maps a result id to (node index + 1); 0 means "no node". Sized by the id |
| 10 | ++ // bound from the SPIR-V header so FindNode() is O(1) instead of O(node_count). |
| 11 | ++ uint32_t id_bound; |
| 12 | ++ uint32_t* node_index_by_id; |
| 13 | + uint32_t entry_point_count; |
| 14 | + uint32_t capability_count; |
| 15 | + uint32_t function_count; |
| 16 | +@@ -511,15 +515,11 @@ static bool IsSpecConstant(const SpvReflectPrvNode* p_node) { |
| 17 | + } |
| 18 | + |
| 19 | + static SpvReflectPrvNode* FindNode(SpvReflectPrvParser* p_parser, uint32_t result_id) { |
| 20 | +- SpvReflectPrvNode* p_node = NULL; |
| 21 | +- for (size_t i = 0; i < p_parser->node_count; ++i) { |
| 22 | +- SpvReflectPrvNode* p_elem = &(p_parser->nodes[i]); |
| 23 | +- if (p_elem->result_id == result_id) { |
| 24 | +- p_node = p_elem; |
| 25 | +- break; |
| 26 | +- } |
| 27 | ++ if (result_id == 0 || result_id >= p_parser->id_bound) { |
| 28 | ++ return NULL; |
| 29 | + } |
| 30 | +- return p_node; |
| 31 | ++ uint32_t index_plus_one = p_parser->node_index_by_id[result_id]; |
| 32 | ++ return index_plus_one ? &(p_parser->nodes[index_plus_one - 1]) : NULL; |
| 33 | + } |
| 34 | + |
| 35 | + static SpvReflectTypeDescription* FindType(SpvReflectShaderModule* p_module, uint32_t type_id) { |
| 36 | +@@ -660,6 +660,8 @@ static void DestroyParser(SpvReflectPrvParser* p_parser) { |
| 37 | + } |
| 38 | + |
| 39 | + SafeFree(p_parser->nodes); |
| 40 | ++ SafeFree(p_parser->node_index_by_id); |
| 41 | ++ p_parser->id_bound = 0; |
| 42 | + SafeFree(p_parser->strings); |
| 43 | + SafeFree(p_parser->source_embedded); |
| 44 | + SafeFree(p_parser->functions); |
| 45 | +@@ -705,6 +707,15 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) { |
| 46 | + if (IsNull(p_parser->nodes)) { |
| 47 | + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; |
| 48 | + } |
| 49 | ++ // Allocate the result id -> node lookup table. Word 3 of the header is the id bound. |
| 50 | ++ p_parser->id_bound = p_spirv[3]; |
| 51 | ++ if (p_parser->id_bound == 0) { |
| 52 | ++ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; |
| 53 | ++ } |
| 54 | ++ p_parser->node_index_by_id = (uint32_t*)calloc(p_parser->id_bound, sizeof(*(p_parser->node_index_by_id))); |
| 55 | ++ if (IsNull(p_parser->node_index_by_id)) { |
| 56 | ++ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; |
| 57 | ++ } |
| 58 | + // Mark all nodes with an invalid state |
| 59 | + for (uint32_t i = 0; i < node_count; ++i) { |
| 60 | + p_parser->nodes[i].op = (SpvOp)INVALID_VALUE; |
| 61 | +@@ -1008,6 +1019,13 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) { |
| 62 | + } break; |
| 63 | + } |
| 64 | + |
| 65 | ++ // Register the node so FindNode() can reach it. Ids are unique, except for |
| 66 | ++ // OpTypeForwardPointer whose result id is re-assigned to the OpTypePointer |
| 67 | ++ // above, so overwriting is what we want. |
| 68 | ++ if (p_node->result_id != 0 && p_node->result_id < p_parser->id_bound) { |
| 69 | ++ p_parser->node_index_by_id[p_node->result_id] = node_index + 1; |
| 70 | ++ } |
| 71 | ++ |
| 72 | + if (p_node->is_type) { |
| 73 | + ++(p_parser->type_count); |
| 74 | + } |
0 commit comments