diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2019-01-10 14:04:01 +0100 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2019-01-10 14:04:01 +0100 |
commit | b629878f45ae4eead5dcccdc20e3eb52c25ba4fd (patch) | |
tree | 900b1c485506c314bda5464b60fdb4e6463ba2ff | |
parent | d92de00cc182a436f4c0340247bde088eee2c921 (diff) | |
download | SPIRV-Cross-b629878f45ae4eead5dcccdc20e3eb52c25ba4fd.tar.gz SPIRV-Cross-b629878f45ae4eead5dcccdc20e3eb52c25ba4fd.tar.bz2 SPIRV-Cross-b629878f45ae4eead5dcccdc20e3eb52c25ba4fd.zip |
Make meta a hashmap.
A flat array was consuming way too much memory and was far too slow to
initialize properly with a very large ID bound (8 million IDs, showed up as #1 hotspot in perf).
Meta struct does not have to be in-order as we never iterate over it in
a meaningful way, so using a hashmap here is reasonable. Very few IDs
should need decorations or meta-data, so this should also be a quite
decent memory save.
For the pathological case, a 6x uplift was observed.
-rw-r--r-- | spirv_cross.cpp | 185 | ||||
-rw-r--r-- | spirv_cross.hpp | 10 | ||||
-rw-r--r-- | spirv_cross_parsed_ir.cpp | 120 | ||||
-rw-r--r-- | spirv_cross_parsed_ir.hpp | 12 | ||||
-rw-r--r-- | spirv_glsl.cpp | 24 | ||||
-rw-r--r-- | spirv_msl.cpp | 10 | ||||
-rw-r--r-- | spirv_parser.cpp | 5 | ||||
-rw-r--r-- | spirv_parser.hpp | 10 | ||||
-rw-r--r-- | spirv_reflect.cpp | 13 |
9 files changed, 248 insertions, 141 deletions
diff --git a/spirv_cross.cpp b/spirv_cross.cpp index db187001..29432a59 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -158,7 +158,7 @@ bool Compiler::block_is_pure(const SPIRBlock &block) string Compiler::to_name(uint32_t id, bool allow_alias) const { - if (allow_alias && ir.ids.at(id).get_type() == TypeType) + if (allow_alias && ir.ids[id].get_type() == TypeType) { // If this type is a simple alias, emit the // name of the original type instead. @@ -174,10 +174,11 @@ string Compiler::to_name(uint32_t id, bool allow_alias) const } } - if (ir.meta[id].decoration.alias.empty()) + auto &alias = ir.get_name(id); + if (alias.empty()) return join("_", id); else - return ir.meta[id].decoration.alias; + return alias; } bool Compiler::function_is_pure(const SPIRFunction &func) @@ -473,17 +474,22 @@ bool Compiler::is_hidden_variable(const SPIRVariable &var, bool include_builtins bool Compiler::is_builtin_type(const SPIRType &type) const { + auto *type_meta = ir.find_meta(type.self); + // We can have builtin structs as well. If one member of a struct is builtin, the struct must also be builtin. - for (auto &m : ir.meta[type.self].members) - if (m.builtin) - return true; + if (type_meta) + for (auto &m : type_meta->members) + if (m.builtin) + return true; return false; } bool Compiler::is_builtin_variable(const SPIRVariable &var) const { - if (var.compat_builtin || ir.meta[var.self].decoration.builtin) + auto *m = ir.find_meta(var.self); + + if (var.compat_builtin || (m && m->decoration.builtin)) return true; else return is_builtin_type(get<SPIRType>(var.basetype)); @@ -491,12 +497,17 @@ bool Compiler::is_builtin_variable(const SPIRVariable &var) const bool Compiler::is_member_builtin(const SPIRType &type, uint32_t index, BuiltIn *builtin) const { - auto &memb = ir.meta[type.self].members; - if (index < memb.size() && memb[index].builtin) + auto *type_meta = ir.find_meta(type.self); + + if (type_meta) { - if (builtin) - *builtin = memb[index].builtin_type; - return true; + auto &memb = type_meta->members; + if (index < memb.size() && memb[index].builtin) + { + if (builtin) + *builtin = memb[index].builtin_type; + return true; + } } return false; @@ -721,36 +732,38 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac // Input if (var.storage == StorageClassInput && interface_variable_exists_in_entry_point(var.self)) { - if (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock)) + if (has_decoration(type.self, DecorationBlock)) + { res.stage_inputs.push_back( - { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); + {var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self)}); + } else - res.stage_inputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.stage_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Subpass inputs else if (var.storage == StorageClassUniformConstant && type.image.dim == DimSubpassData) { - res.subpass_inputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.subpass_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Outputs else if (var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self)) { - if (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock)) + if (has_decoration(type.self, DecorationBlock)) + { res.stage_outputs.push_back( - { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); + {var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self)}); + } else - res.stage_outputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.stage_outputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // UBOs - else if (type.storage == StorageClassUniform && - (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock))) + else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBlock)) { res.uniform_buffers.push_back( { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); } // Old way to declare SSBOs. - else if (type.storage == StorageClassUniform && - (ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock))) + else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBufferBlock)) { res.storage_buffers.push_back( { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); @@ -767,34 +780,34 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac // There can only be one push constant block, but keep the vector in case this restriction is lifted // in the future. res.push_constant_buffers.push_back( - { var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + { var.self, var.basetype, type.self, get_name(var.self) }); } // Images else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image && type.image.sampled == 2) { - res.storage_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.storage_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Separate images else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image && type.image.sampled == 1) { - res.separate_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.separate_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Separate samplers else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Sampler) { - res.separate_samplers.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.separate_samplers.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Textures else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::SampledImage) { - res.sampled_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.sampled_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } // Atomic counters else if (type.storage == StorageClassAtomicCounter) { - res.atomic_counters.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias }); + res.atomic_counters.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); } }); @@ -919,7 +932,7 @@ void Compiler::flatten_interface_block(uint32_t id) { auto &var = get<SPIRVariable>(id); auto &type = get<SPIRType>(var.basetype); - auto &flags = ir.meta.at(type.self).decoration.decoration_flags; + auto &flags = ir.meta[type.self].decoration.decoration_flags; if (!type.array.empty()) SPIRV_CROSS_THROW("Type is array of UBOs."); @@ -942,7 +955,7 @@ void Compiler::flatten_interface_block(uint32_t id) SPIRV_CROSS_THROW("Member type cannot be struct."); // Inherit variable name from interface block name. - ir.meta.at(var.self).decoration.alias = ir.meta.at(type.self).decoration.alias; + ir.meta[var.self].decoration.alias = ir.meta[type.self].decoration.alias; auto storage = var.storage; if (storage == StorageClassUniform) @@ -1105,19 +1118,17 @@ const std::string &Compiler::get_member_name(uint32_t id, uint32_t index) const void Compiler::set_member_qualified_name(uint32_t type_id, uint32_t index, const std::string &name) { - ir.meta.at(type_id).members.resize(max(ir.meta[type_id].members.size(), size_t(index) + 1)); - ir.meta.at(type_id).members[index].qualified_alias = name; + ir.meta[type_id].members.resize(max(ir.meta[type_id].members.size(), size_t(index) + 1)); + ir.meta[type_id].members[index].qualified_alias = name; } -const std::string &Compiler::get_member_qualified_name(uint32_t type_id, uint32_t index) const +const string &Compiler::get_member_qualified_name(uint32_t type_id, uint32_t index) const { - const static string empty; - - auto &m = ir.meta.at(type_id); - if (index < m.members.size()) - return m.members[index].qualified_alias; + auto *m = ir.find_meta(type_id); + if (m && index < m->members.size()) + return m->members[index].qualified_alias; else - return empty; + return ir.get_empty_string(); } uint32_t Compiler::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const @@ -1162,7 +1173,7 @@ StorageClass Compiler::get_storage_class(uint32_t id) const const std::string &Compiler::get_name(uint32_t id) const { - return ir.meta.at(id).decoration.alias; + return ir.get_name(id); } const std::string Compiler::get_fallback_name(uint32_t id) const @@ -1216,7 +1227,11 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration) bool Compiler::get_binary_offset_for_decoration(uint32_t id, spv::Decoration decoration, uint32_t &word_offset) const { - auto &word_offsets = ir.meta.at(id).decoration_word_offset; + auto *m = ir.find_meta(id); + if (!m) + return false; + + auto &word_offsets = m->decoration_word_offset; auto itr = word_offsets.find(decoration); if (itr == end(word_offsets)) return false; @@ -1445,32 +1460,50 @@ bool Compiler::traverse_all_reachable_opcodes(const SPIRFunction &func, OpcodeHa uint32_t Compiler::type_struct_member_offset(const SPIRType &type, uint32_t index) const { - // Decoration must be set in valid SPIR-V, otherwise throw. - auto &dec = ir.meta[type.self].members.at(index); - if (dec.decoration_flags.get(DecorationOffset)) - return dec.offset; + auto *type_meta = ir.find_meta(type.self); + if (type_meta) + { + // Decoration must be set in valid SPIR-V, otherwise throw. + auto &dec = type_meta->members[index]; + if (dec.decoration_flags.get(DecorationOffset)) + return dec.offset; + else + SPIRV_CROSS_THROW("Struct member does not have Offset set."); + } else SPIRV_CROSS_THROW("Struct member does not have Offset set."); } uint32_t Compiler::type_struct_member_array_stride(const SPIRType &type, uint32_t index) const { - // Decoration must be set in valid SPIR-V, otherwise throw. - // ArrayStride is part of the array type not OpMemberDecorate. - auto &dec = ir.meta[type.member_types[index]].decoration; - if (dec.decoration_flags.get(DecorationArrayStride)) - return dec.array_stride; + auto *type_meta = ir.find_meta(type.member_types[index]); + if (type_meta) + { + // Decoration must be set in valid SPIR-V, otherwise throw. + // ArrayStride is part of the array type not OpMemberDecorate. + auto &dec = type_meta->decoration; + if (dec.decoration_flags.get(DecorationArrayStride)) + return dec.array_stride; + else + SPIRV_CROSS_THROW("Struct member does not have ArrayStride set."); + } else - SPIRV_CROSS_THROW("Struct member does not have ArrayStride set."); + SPIRV_CROSS_THROW("Struct member does not have Offset set."); } uint32_t Compiler::type_struct_member_matrix_stride(const SPIRType &type, uint32_t index) const { - // Decoration must be set in valid SPIR-V, otherwise throw. - // MatrixStride is part of OpMemberDecorate. - auto &dec = ir.meta[type.self].members[index]; - if (dec.decoration_flags.get(DecorationMatrixStride)) - return dec.matrix_stride; + auto *type_meta = ir.find_meta(type.self); + if (type_meta) + { + // Decoration must be set in valid SPIR-V, otherwise throw. + // MatrixStride is part of OpMemberDecorate. + auto &dec = type_meta->members[index]; + if (dec.decoration_flags.get(DecorationMatrixStride)) + return dec.matrix_stride; + else + SPIRV_CROSS_THROW("Struct member does not have MatrixStride set."); + } else SPIRV_CROSS_THROW("Struct member does not have MatrixStride set."); } @@ -3610,15 +3643,18 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_ bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const { - return ir.meta.at(id).hlsl_is_magic_counter_buffer; + auto *m = ir.find_meta(id); + return m && m->hlsl_is_magic_counter_buffer; } bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const { + auto *m = ir.find_meta(id); + // First, check for the proper decoration. - if (ir.meta[id].hlsl_magic_counter_buffer != 0) + if (m && m->hlsl_magic_counter_buffer != 0) { - counter_id = ir.meta[id].hlsl_magic_counter_buffer; + counter_id = m->hlsl_magic_counter_buffer; return true; } else @@ -3685,8 +3721,10 @@ std::string Compiler::get_remapped_declared_block_name(uint32_t id) const { auto &var = get<SPIRVariable>(id); auto &type = get<SPIRType>(var.basetype); - auto &block_name = ir.meta[type.self].decoration.alias; - return block_name.empty() ? get_block_fallback_name(id) : block_name; + + auto *type_meta = ir.find_meta(type.self); + auto *block_name = type_meta ? &type_meta->decoration.alias : nullptr; + return (!block_name || block_name->empty()) ? get_block_fallback_name(id) : *block_name; } } @@ -3733,15 +3771,20 @@ bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &resul Bitset Compiler::combined_decoration_for_member(const SPIRType &type, uint32_t index) const { Bitset flags; - auto &memb = ir.meta[type.self].members; - if (index >= memb.size()) - return flags; - auto &dec = memb[index]; - - // If our type is a struct, traverse all the members as well recursively. - flags.merge_or(dec.decoration_flags); - for (uint32_t i = 0; i < type.member_types.size(); i++) - flags.merge_or(combined_decoration_for_member(get<SPIRType>(type.member_types[i]), i)); + auto *type_meta = ir.find_meta(type.self); + + if (type_meta) + { + auto &memb = type_meta->members; + if (index >= memb.size()) + return flags; + auto &dec = memb[index]; + + // If our type is a struct, traverse all the members as well recursively. + flags.merge_or(dec.decoration_flags); + for (uint32_t i = 0; i < type.member_types.size(); i++) + flags.merge_or(combined_decoration_for_member(get<SPIRType>(type.member_types[i]), i)); + } return flags; } diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 400022ef..82e2e333 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -562,7 +562,7 @@ protected: T &set(uint32_t id, P &&... args) { ir.add_typed_id(static_cast<Types>(T::type), id); - auto &var = variant_set<T>(ir.ids.at(id), std::forward<P>(args)...); + auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...); var.self = id; return var; } @@ -570,13 +570,13 @@ protected: template <typename T> T &get(uint32_t id) { - return variant_get<T>(ir.ids.at(id)); + return variant_get<T>(ir.ids[id]); } template <typename T> T *maybe_get(uint32_t id) { - if (ir.ids.at(id).get_type() == static_cast<Types>(T::type)) + if (ir.ids[id].get_type() == static_cast<Types>(T::type)) return &get<T>(id); else return nullptr; @@ -585,13 +585,13 @@ protected: template <typename T> const T &get(uint32_t id) const { - return variant_get<T>(ir.ids.at(id)); + return variant_get<T>(ir.ids[id]); } template <typename T> const T *maybe_get(uint32_t id) const { - if (ir.ids.at(id).get_type() == static_cast<Types>(T::type)) + if (ir.ids[id].get_type() == static_cast<Types>(T::type)) return &get<T>(id); else return nullptr; diff --git a/spirv_cross_parsed_ir.cpp b/spirv_cross_parsed_ir.cpp index 6d80fcb3..82bc5611 100644 --- a/spirv_cross_parsed_ir.cpp +++ b/spirv_cross_parsed_ir.cpp @@ -26,7 +26,6 @@ namespace spirv_cross void ParsedIR::set_id_bounds(uint32_t bounds) { ids.resize(bounds); - meta.resize(bounds); block_meta.resize(bounds); } @@ -66,19 +65,24 @@ static string ensure_valid_identifier(const string &name, bool member) const string &ParsedIR::get_name(uint32_t id) const { - return meta[id].decoration.alias; + auto *m = find_meta(id); + if (m) + return m->decoration.alias; + else + return empty_string; } const string &ParsedIR::get_member_name(uint32_t id, uint32_t index) const { - auto &m = meta[id]; - if (index >= m.members.size()) + auto *m = find_meta(id); + if (m) { - static string empty; - return empty; + if (index >= m->members.size()) + return empty_string; + return m->members[index].alias; } - - return m.members[index].alias; + else + return empty_string; } void ParsedIR::set_name(uint32_t id, const string &name) @@ -274,7 +278,10 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const // Some flags like non-writable, non-readable are actually found // as member decorations. If all members have a decoration set, propagate // the decoration up as a regular variable decoration. - Bitset base_flags = meta[var.self].decoration.decoration_flags; + Bitset base_flags; + auto *m = find_meta(var.self); + if (m) + base_flags = m->decoration.decoration_flags; if (type.member_types.empty()) return base_flags; @@ -289,14 +296,15 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const const Bitset &ParsedIR::get_member_decoration_bitset(uint32_t id, uint32_t index) const { - auto &m = meta[id]; - if (index >= m.members.size()) + auto *m = find_meta(id); + if (m) { - static const Bitset cleared = {}; - return cleared; + if (index >= m->members.size()) + return cleared_bitset; + return m->members[index].decoration_flags; } - - return m.members[index].decoration_flags; + else + return cleared_bitset; } bool ParsedIR::has_decoration(uint32_t id, Decoration decoration) const @@ -306,7 +314,11 @@ bool ParsedIR::has_decoration(uint32_t id, Decoration decoration) const uint32_t ParsedIR::get_decoration(uint32_t id, Decoration decoration) const { - auto &dec = meta[id].decoration; + auto *m = find_meta(id); + if (!m) + return 0; + + auto &dec = m->decoration; if (!dec.decoration_flags.get(decoration)) return 0; @@ -343,11 +355,14 @@ uint32_t ParsedIR::get_decoration(uint32_t id, Decoration decoration) const const string &ParsedIR::get_decoration_string(uint32_t id, Decoration decoration) const { - auto &dec = meta[id].decoration; - static const string empty; + auto *m = find_meta(id); + if (!m) + return empty_string; + + auto &dec = m->decoration; if (!dec.decoration_flags.get(decoration)) - return empty; + return empty_string; switch (decoration) { @@ -355,7 +370,7 @@ const string &ParsedIR::get_decoration_string(uint32_t id, Decoration decoration return dec.hlsl_semantic; default: - return empty; + return empty_string; } } @@ -428,11 +443,14 @@ bool ParsedIR::has_member_decoration(uint32_t id, uint32_t index, Decoration dec uint32_t ParsedIR::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const { - auto &m = meta[id]; - if (index >= m.members.size()) + auto *m = find_meta(id); + if (!m) return 0; - auto &dec = m.members[index]; + if (index >= m->members.size()) + return 0; + + auto &dec = m->members[index]; if (!dec.decoration_flags.get(decoration)) return 0; @@ -459,8 +477,14 @@ uint32_t ParsedIR::get_member_decoration(uint32_t id, uint32_t index, Decoration const Bitset &ParsedIR::get_decoration_bitset(uint32_t id) const { - auto &dec = meta[id].decoration; - return dec.decoration_flags; + auto *m = find_meta(id); + if (m) + { + auto &dec = m->decoration; + return dec.decoration_flags; + } + else + return cleared_bitset; } void ParsedIR::set_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration, const string &argument) @@ -482,22 +506,25 @@ void ParsedIR::set_member_decoration_string(uint32_t id, uint32_t index, Decorat const string &ParsedIR::get_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration) const { - static const string empty; - auto &m = meta[id]; - - if (!has_member_decoration(id, index, decoration)) - return empty; + auto *m = find_meta(id); + if (m) + { + if (!has_member_decoration(id, index, decoration)) + return empty_string; - auto &dec = m.members[index]; + auto &dec = m->members[index]; - switch (decoration) - { - case DecorationHlslSemanticGOOGLE: - return dec.hlsl_semantic; + switch (decoration) + { + case DecorationHlslSemanticGOOGLE: + return dec.hlsl_semantic; - default: - return empty; + default: + return empty_string; + } } + else + return empty_string; } void ParsedIR::unset_member_decoration(uint32_t id, uint32_t index, Decoration decoration) @@ -545,7 +572,6 @@ uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount) auto curr_bound = ids.size(); auto new_bound = curr_bound + incr_amount; ids.resize(new_bound); - meta.resize(new_bound); block_meta.resize(new_bound); return uint32_t(curr_bound); } @@ -601,4 +627,22 @@ void ParsedIR::add_typed_id(Types type, uint32_t id) } } +const Meta *ParsedIR::find_meta(uint32_t id) const +{ + auto itr = meta.find(id); + if (itr != end(meta)) + return &itr->second; + else + return nullptr; +} + +Meta *ParsedIR::find_meta(uint32_t id) +{ + auto itr = meta.find(id); + if (itr != end(meta)) + return &itr->second; + else + return nullptr; +} + } // namespace spirv_cross diff --git a/spirv_cross_parsed_ir.hpp b/spirv_cross_parsed_ir.hpp index b6e51f8f..c3c4612e 100644 --- a/spirv_cross_parsed_ir.hpp +++ b/spirv_cross_parsed_ir.hpp @@ -43,7 +43,7 @@ public: std::vector<Variant> ids; // Various meta data for IDs, decorations, names, etc. - std::vector<Meta> meta; + std::unordered_map<uint32_t, Meta> meta; // Holds all IDs which have a certain type. // This is needed so we can iterate through a specific kind of resource quickly, @@ -156,6 +156,14 @@ public: void reset_all_of_type(Types type); + Meta *find_meta(uint32_t id); + const Meta *find_meta(uint32_t id) const; + + const std::string &get_empty_string() const + { + return empty_string; + } + private: template <typename T> T &get(uint32_t id) @@ -170,6 +178,8 @@ private: } uint32_t loop_iteration_depth = 0; + std::string empty_string; + Bitset cleared_bitset; }; } // namespace spirv_cross diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index be32c327..81920a9b 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -965,7 +965,7 @@ uint32_t CompilerGLSL::type_to_packed_alignment(const SPIRType &type, const Bits uint32_t alignment = 0; for (uint32_t i = 0; i < type.member_types.size(); i++) { - auto member_flags = ir.meta[type.self].members.at(i).decoration_flags; + auto member_flags = ir.meta[type.self].members[i].decoration_flags; alignment = max(alignment, type_to_packed_alignment(get<SPIRType>(type.member_types[i]), member_flags, packing)); } @@ -1069,7 +1069,7 @@ uint32_t CompilerGLSL::type_to_packed_size(const SPIRType &type, const Bitset &f for (uint32_t i = 0; i < type.member_types.size(); i++) { - auto member_flags = ir.meta[type.self].members.at(i).decoration_flags; + auto member_flags = ir.meta[type.self].members[i].decoration_flags; auto &member_type = get<SPIRType>(type.member_types[i]); uint32_t packed_alignment = type_to_packed_alignment(member_type, member_flags, packing); @@ -1142,7 +1142,7 @@ bool CompilerGLSL::buffer_is_packing_standard(const SPIRType &type, BufferPackin for (uint32_t i = 0; i < type.member_types.size(); i++) { auto &memb_type = get<SPIRType>(type.member_types[i]); - auto member_flags = ir.meta[type.self].members.at(i).decoration_flags; + auto member_flags = ir.meta[type.self].members[i].decoration_flags; // Verify alignment rules. uint32_t packed_alignment = type_to_packed_alignment(memb_type, member_flags, packing); @@ -2012,7 +2012,7 @@ void CompilerGLSL::fixup_image_load_store_access() // Solve this by making the image access as restricted as possible and loosen up if we need to. // If any no-read/no-write flags are actually set, assume that the compiler knows what it's doing. - auto &flags = ir.meta.at(var).decoration.decoration_flags; + auto &flags = ir.meta[var].decoration.decoration_flags; if (!flags.get(DecorationNonWritable) && !flags.get(DecorationNonReadable)) { flags.set(DecorationNonWritable); @@ -2466,7 +2466,7 @@ string CompilerGLSL::dereference_expression(const std::string &expr) // If this expression starts with an address-of operator ('&'), then // just return the part after the operator. // TODO: Strip parens if unnecessary? - if (expr.at(0) == '&') + if (expr.front() == '&') return expr.substr(1); else return join('*', expr); @@ -2477,7 +2477,7 @@ string CompilerGLSL::address_of_expression(const std::string &expr) // If this expression starts with a dereference operator ('*'), then // just return the part after the operator. // TODO: Strip parens if unnecessary? - if (expr.at(0) == '*') + if (expr.front() == '*') return expr.substr(1); else return join('&', expr); @@ -8075,7 +8075,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) auto *var = maybe_get_backing_variable(ops[2]); if (var) { - auto &flags = ir.meta.at(var->self).decoration.decoration_flags; + auto &flags = ir.meta[var->self].decoration.decoration_flags; if (flags.get(DecorationNonReadable)) { flags.clear(DecorationNonReadable); @@ -8223,7 +8223,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) auto *var = maybe_get_backing_variable(ops[0]); if (var) { - auto &flags = ir.meta.at(var->self).decoration.decoration_flags; + auto &flags = ir.meta[var->self].decoration.decoration_flags; if (flags.get(DecorationNonWritable)) { flags.clear(DecorationNonWritable); @@ -9413,7 +9413,7 @@ void CompilerGLSL::flatten_buffer_block(uint32_t id) auto &var = get<SPIRVariable>(id); auto &type = get<SPIRType>(var.basetype); auto name = to_name(type.self, false); - auto &flags = ir.meta.at(type.self).decoration.decoration_flags; + auto &flags = ir.meta[type.self].decoration.decoration_flags; if (!type.array.empty()) SPIRV_CROSS_THROW(name + " is an array of UBOs."); @@ -9438,7 +9438,7 @@ bool CompilerGLSL::check_atomic_image(uint32_t id) auto *var = maybe_get_backing_variable(id); if (var) { - auto &flags = ir.meta.at(var->self).decoration.decoration_flags; + auto &flags = ir.meta[var->self].decoration.decoration_flags; if (flags.get(DecorationNonWritable) || flags.get(DecorationNonReadable)) { flags.clear(DecorationNonWritable); @@ -10547,7 +10547,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) { // If we cannot return arrays, we will have a special out argument we can write to instead. // The backend is responsible for setting this up, and redirection the return values as appropriate. - if (ir.ids.at(block.return_value).get_type() != TypeUndef) + if (ir.ids[block.return_value].get_type() != TypeUndef) emit_array_copy("SPIRV_Cross_return_value", block.return_value); if (!block_is_outside_flow_control_from_block(get<SPIRBlock>(current_function->entry_block), block) || @@ -10559,7 +10559,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) else { // OpReturnValue can return Undef, so don't emit anything for this case. - if (ir.ids.at(block.return_value).get_type() != TypeUndef) + if (ir.ids[block.return_value].get_type() != TypeUndef) statement("return ", to_expression(block.return_value), ";"); } } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index f051e481..79bd3c9a 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -4071,7 +4071,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in // index as the location. uint32_t CompilerMSL::get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp) { - auto &m = ir.meta.at(type_id); + auto &m = ir.meta[type_id]; if (index < m.members.size()) { auto &dec = m.members[index]; @@ -4287,7 +4287,7 @@ string CompilerMSL::entry_point_args(bool append_comma) { case SPIRType::Struct: { - auto &m = ir.meta.at(type.self); + auto &m = ir.meta[type.self]; if (m.members.size() == 0) break; if (!type.array.empty()) @@ -4529,9 +4529,9 @@ string CompilerMSL::to_name(uint32_t id, bool allow_alias) const { if (current_function && (current_function->self == ir.default_entry_point)) { - string qual_name = ir.meta.at(id).decoration.qualified_alias; - if (!qual_name.empty()) - return qual_name; + auto *m = ir.find_meta(id); + if (m && !m->decoration.qualified_alias.empty()) + return m->decoration.qualified_alias; } return Compiler::to_name(id, allow_alias); } diff --git a/spirv_parser.cpp b/spirv_parser.cpp index 205305dd..2f76144e 100644 --- a/spirv_parser.cpp +++ b/spirv_parser.cpp @@ -1063,8 +1063,11 @@ bool Parser::types_are_logically_equivalent(const SPIRType &a, const SPIRType &b bool Parser::variable_storage_is_aliased(const SPIRVariable &v) const { auto &type = get<SPIRType>(v.basetype); + + auto *type_meta = ir.find_meta(type.self); + bool ssbo = v.storage == StorageClassStorageBuffer || - ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock); + (type_meta && type_meta->decoration.decoration_flags.get(DecorationBufferBlock)); bool image = type.basetype == SPIRType::Image; bool counter = type.basetype == SPIRType::AtomicCounter; diff --git a/spirv_parser.hpp b/spirv_parser.hpp index 6cd93884..cc153152 100644 --- a/spirv_parser.hpp +++ b/spirv_parser.hpp @@ -48,7 +48,7 @@ private: T &set(uint32_t id, P &&... args) { ir.add_typed_id(static_cast<Types>(T::type), id); - auto &var = variant_set<T>(ir.ids.at(id), std::forward<P>(args)...); + auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...); var.self = id; return var; } @@ -56,13 +56,13 @@ private: template <typename T> T &get(uint32_t id) { - return variant_get<T>(ir.ids.at(id)); + return variant_get<T>(ir.ids[id]); } template <typename T> T *maybe_get(uint32_t id) { - if (ir.ids.at(id).get_type() == static_cast<Types>(T::type)) + if (ir.ids[id].get_type() == static_cast<Types>(T::type)) return &get<T>(id); else return nullptr; @@ -71,13 +71,13 @@ private: template <typename T> const T &get(uint32_t id) const { - return variant_get<T>(ir.ids.at(id)); + return variant_get<T>(ir.ids[id]); } template <typename T> const T *maybe_get(uint32_t id) const { - if (ir.ids.at(id).get_type() == T::type) + if (ir.ids[id].get_type() == T::type) return &get<T>(id); else return nullptr; diff --git a/spirv_reflect.cpp b/spirv_reflect.cpp index 00307315..39161b14 100644 --- a/spirv_reflect.cpp +++ b/spirv_reflect.cpp @@ -565,9 +565,16 @@ void CompilerReflection::emit_specialization_constants() string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const { - auto &memb = ir.meta[type.self].members; - if (index < memb.size() && !memb[index].alias.empty()) - return memb[index].alias; + auto *type_meta = ir.find_meta(type.self); + + if (type_meta) + { + auto &memb = type_meta->members; + if (index < memb.size() && !memb[index].alias.empty()) + return memb[index].alias; + else + return join("_m", index); + } else return join("_m", index); } |