summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2019-01-10 14:04:01 +0100
committerHans-Kristian Arntzen <post@arntzen-software.no>2019-01-10 14:04:01 +0100
commitb629878f45ae4eead5dcccdc20e3eb52c25ba4fd (patch)
tree900b1c485506c314bda5464b60fdb4e6463ba2ff
parentd92de00cc182a436f4c0340247bde088eee2c921 (diff)
downloadSPIRV-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.cpp185
-rw-r--r--spirv_cross.hpp10
-rw-r--r--spirv_cross_parsed_ir.cpp120
-rw-r--r--spirv_cross_parsed_ir.hpp12
-rw-r--r--spirv_glsl.cpp24
-rw-r--r--spirv_msl.cpp10
-rw-r--r--spirv_parser.cpp5
-rw-r--r--spirv_parser.hpp10
-rw-r--r--spirv_reflect.cpp13
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);
}