]> git.tdb.fi Git - libs/gl.git/commitdiff
Store program resource information in vectors instead of maps
authorMikko Rasa <tdb@tdb.fi>
Fri, 2 Apr 2021 11:45:38 +0000 (14:45 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 2 Apr 2021 12:44:53 +0000 (15:44 +0300)
source/core/program.cpp
source/core/program.h
source/render/programdata.cpp

index 4b53b8fe2f28e7e812e605654d6d7d64ec695aeb..999a94ad75a6d6c3edc1899c9fb0944c69a373eb 100644 (file)
@@ -1,6 +1,6 @@
-#include <algorithm>
 #include <cstring>
 #include <set>
+#include <msp/core/algorithm.h>
 #include <msp/core/hash.h>
 #include <msp/core/maputils.h>
 #include <msp/gl/extensions/arb_es2_compatibility.h>
@@ -308,16 +308,17 @@ void Program::link()
                collect_attributes();
        }
 
-       for(UniformMap::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
-               require_type(i->second.type);
-       for(AttributeMap::const_iterator i=attributes.begin(); i!=attributes.end(); ++i)
-               require_type(i->second.type);
+       for(vector<UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+               require_type(i->type);
+       for(vector<AttributeInfo>::const_iterator i=attributes.begin(); i!=attributes.end(); ++i)
+               require_type(i->type);
 }
 
 void Program::query_uniforms()
 {
        unsigned count = get_program_i(id, GL_ACTIVE_UNIFORMS);
-       vector<UniformInfo *> uniforms_by_index(count);
+       uniforms.reserve(count);
+       vector<string> uniform_names(count);
        for(unsigned i=0; i<count; ++i)
        {
                char name[128];
@@ -332,25 +333,36 @@ void Program::query_uniforms()
                        if(len>3 && !strcmp(name+len-3, "[0]"))
                                name[len-3] = 0;
 
-                       UniformInfo &info = uniforms[name];
+                       uniforms.push_back(UniformInfo());
+                       UniformInfo &info = uniforms.back();
                        info.name = name;
                        info.array_size = size;
                        info.type = from_gl_type(type);
-                       uniforms_by_index[i] = &info;
+                       uniform_names[i] = name;
                }
        }
 
+       sort(uniforms, &uniform_name_compare);
+
        if(ARB_uniform_buffer_object)
+       {
+               vector<UniformInfo *> uniforms_by_index(count);
+               for(unsigned i=0; i<count; ++i)
+                       if(!uniform_names[i].empty())
+                               // The element is already known to be present
+                               uniforms_by_index[i] = &*lower_bound(uniforms, uniform_names[i], &name_search<UniformInfo>);
                query_uniform_blocks(uniforms_by_index);
+       }
 
-       UniformBlockInfo &default_block = uniform_blocks[string()];
+       uniform_blocks.push_back(UniformBlockInfo());
+       UniformBlockInfo &default_block = uniform_blocks.back();
 
-       for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
-               if(!i->second.block)
+       for(vector<UniformInfo>::iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+               if(!i->block)
                {
-                       i->second.location = glGetUniformLocation(id, i->second.name.c_str());
-                       i->second.block = &default_block;
-                       default_block.uniforms.push_back(&i->second);
+                       i->location = glGetUniformLocation(id, i->name.c_str());
+                       i->block = &default_block;
+                       default_block.uniforms.push_back(&*i);
                }
 
        default_block.layout_hash = compute_layout_hash(default_block.uniforms);
@@ -362,12 +374,15 @@ void Program::query_uniform_blocks(const vector<UniformInfo *> &uniforms_by_inde
 {
        std::set<unsigned> used_bind_points;
        unsigned count = get_program_i(id, GL_ACTIVE_UNIFORM_BLOCKS);
+       // Reserve an extra index for the default block
+       uniform_blocks.reserve(count+1);
        for(unsigned i=0; i<count; ++i)
        {
                char name[128];
                int len;
                glGetActiveUniformBlockName(id, i, sizeof(name), &len, name);
-               UniformBlockInfo &info = uniform_blocks[name];
+               uniform_blocks.push_back(UniformBlockInfo());
+               UniformBlockInfo &info = uniform_blocks.back();
                info.name = name;
 
                int value;
@@ -430,6 +445,7 @@ void Program::query_uniform_blocks(const vector<UniformInfo *> &uniforms_by_inde
 void Program::query_attributes()
 {
        unsigned count = get_program_i(id, GL_ACTIVE_ATTRIBUTES);
+       attributes.reserve(count);
        for(unsigned i=0; i<count; ++i)
        {
                char name[128];
@@ -442,7 +458,8 @@ void Program::query_attributes()
                        if(len>3 && !strcmp(name+len-3, "[0]"))
                                name[len-3] = 0;
 
-                       AttributeInfo &info = attributes[name];
+                       attributes.push_back(AttributeInfo());
+                       AttributeInfo &info = attributes.back();
                        info.name = name;
                        info.location = glGetAttribLocation(id, name);
                        info.array_size = size;
@@ -455,14 +472,17 @@ void Program::collect_uniforms()
 {
        const SpirVModule &mod = static_cast<const SpirVModule &>(*module);
 
-       UniformBlockInfo &default_block = uniform_blocks[string()];
+       // Prepare the default block
+       uniform_blocks.push_back(UniformBlockInfo());
+       vector<vector<string> > block_uniform_names(1);
 
        const vector<SpirVModule::Variable> &variables = mod.get_variables();
        for(vector<SpirVModule::Variable>::const_iterator i=variables.begin(); i!=variables.end(); ++i)
        {
                if(i->storage==SpirVModule::UNIFORM && i->struct_type)
                {
-                       UniformBlockInfo &info = uniform_blocks[i->struct_type->name];
+                       uniform_blocks.push_back(UniformBlockInfo());
+                       UniformBlockInfo &info = uniform_blocks.back();
                        info.name = i->struct_type->name;
                        info.bind_point = i->binding;
                        info.data_size = i->struct_type->size;
@@ -470,28 +490,41 @@ void Program::collect_uniforms()
                        string prefix;
                        if(!i->name.empty())
                                prefix = i->struct_type->name+".";
-                       collect_block_uniforms(info, *i->struct_type, prefix, 0);
-
-                       info.layout_hash = compute_layout_hash(info.uniforms);
+                       block_uniform_names.push_back(vector<string>());
+                       collect_block_uniforms(*i->struct_type, prefix, 0, block_uniform_names.back());
                }
                else if(i->storage==SpirVModule::UNIFORM_CONSTANT && i->location>=0)
                {
-                       UniformInfo &info = uniforms[i->name];
+                       block_uniform_names[0].push_back(i->name);
+                       uniforms.push_back(UniformInfo());
+                       UniformInfo &info = uniforms.back();
                        info.name = i->name;
-                       info.block = &default_block;
                        info.location = i->location;
                        info.array_size = i->array_size;
                        info.type = i->type;
-                       default_block.uniforms.push_back(&info);
                }
        }
 
-       default_block.layout_hash = compute_layout_hash(default_block.uniforms);
+       sort(uniforms, &uniform_name_compare);
+
+       for(unsigned i=0; i<uniform_blocks.size(); ++i)
+       {
+               UniformBlockInfo &block = uniform_blocks[i];
+               const vector<string> &names = block_uniform_names[i];
+               for(vector<string>::const_iterator j=names.begin(); j!=names.end(); ++j)
+               {
+                       // The element is already known to be present
+                       UniformInfo &uni = *lower_bound(uniforms, *j, &name_search<UniformInfo>);
+                       block.uniforms.push_back(&uni);
+                       uni.block = &block;
+               }
+               block.layout_hash = compute_layout_hash(block.uniforms);
+       }
 
        update_layout_hash();
 }
 
-void Program::collect_block_uniforms(UniformBlockInfo &block, const SpirVModule::Structure &strct, const string &prefix, unsigned base_offset)
+void Program::collect_block_uniforms(const SpirVModule::Structure &strct, const string &prefix, unsigned base_offset, vector<string> &uniform_names)
 {
        for(vector<SpirVModule::StructMember>::const_iterator i=strct.members.begin(); i!=strct.members.end(); ++i)
        {
@@ -501,23 +534,23 @@ void Program::collect_block_uniforms(UniformBlockInfo &block, const SpirVModule:
                        if(i->array_size)
                        {
                                for(unsigned j=0; j<i->array_size; ++j, offset+=i->array_stride)
-                                       collect_block_uniforms(block, *i->struct_type, format("%s%s[%d].", prefix, i->name, j), offset);
+                                       collect_block_uniforms(*i->struct_type, format("%s%s[%d].", prefix, i->name, j), offset, uniform_names);
                        }
                        else
-                               collect_block_uniforms(block, *i->struct_type, prefix+i->name+".", offset);
+                               collect_block_uniforms(*i->struct_type, prefix+i->name+".", offset, uniform_names);
                }
                else
                {
                        string name = prefix+i->name;
-                       UniformInfo &info = uniforms[name];
+                       uniform_names.push_back(name);
+                       uniforms.push_back(UniformInfo());
+                       UniformInfo &info = uniforms.back();
                        info.name = name;
-                       info.block = &block;
                        info.offset = offset;
                        info.array_size = i->array_size;
                        info.array_stride = i->array_stride;
                        info.matrix_stride = i->matrix_stride;
                        info.type = i->type;
-                       block.uniforms.push_back(&info);
                }
        }
 }
@@ -533,7 +566,8 @@ void Program::collect_attributes()
                        for(vector<const SpirVModule::Variable *>::const_iterator j=i->globals.begin(); j!=i->globals.end(); ++j)
                                if((*j)->storage==SpirVModule::INPUT)
                                {
-                                       AttributeInfo &info = attributes[(*j)->name];
+                                       attributes.push_back(AttributeInfo());
+                                       AttributeInfo &info = attributes.back();
                                        info.name = (*j)->name;
                                        info.location = (*j)->location;
                                        info.array_size = (*j)->array_size;
@@ -545,8 +579,8 @@ void Program::collect_attributes()
 void Program::update_layout_hash()
 {
        string layout_descriptor;
-       for(UniformBlockMap::const_iterator i=uniform_blocks.begin(); i!=uniform_blocks.end(); ++i)
-               layout_descriptor += format("%d:%x\n", i->second.bind_point, i->second.layout_hash);
+       for(vector<UniformBlockInfo>::const_iterator i=uniform_blocks.begin(); i!=uniform_blocks.end(); ++i)
+               layout_descriptor += format("%d:%x\n", i->bind_point, i->layout_hash);
        uniform_layout_hash = hash32(layout_descriptor);
 }
 
@@ -563,6 +597,17 @@ bool Program::uniform_location_compare(const UniformInfo *uni1, const UniformInf
        return uni1->location<uni2->location;
 }
 
+bool Program::uniform_name_compare(const UniformInfo &uni1, const UniformInfo &uni2)
+{
+       return uni1.name<uni2.name;
+}
+
+template<typename T>
+bool Program::name_search(const T &item, const string &name)
+{
+       return item.name<name;
+}
+
 string Program::get_info_log() const
 {
        GLsizei len = get_program_i(id, GL_INFO_LOG_LENGTH);
@@ -574,12 +619,18 @@ string Program::get_info_log() const
 
 const Program::UniformBlockInfo &Program::get_uniform_block_info(const string &name) const
 {
-       return get_item(uniform_blocks, name);
+       for(vector<UniformBlockInfo>::const_iterator i=uniform_blocks.begin(); i!=uniform_blocks.end(); ++i)
+               if(i->name==name)
+                       return *i;
+       throw key_error(name);
 }
 
 const Program::UniformInfo &Program::get_uniform_info(const string &name) const
 {
-       return get_item(uniforms, name);
+       vector<UniformInfo>::const_iterator i = lower_bound(uniforms, name, &name_search<UniformInfo>);
+       if(i==uniforms.end() || i->name!=name)
+               throw key_error(name);
+       return *i;
 }
 
 int Program::get_uniform_location(const string &name) const
@@ -587,16 +638,16 @@ int Program::get_uniform_location(const string &name) const
        if(name[name.size()-1]==']')
                throw invalid_argument("Program::get_uniform_location");
 
-       UniformMap::const_iterator i = uniforms.find(name);
-       if(i==uniforms.end())
-               return -1;
-
-       return i->second.block->bind_point<0 ? i->second.location : -1;
+       vector<UniformInfo>::const_iterator i = lower_bound(uniforms, name, &name_search<UniformInfo>);
+       return i!=uniforms.end() && i->name==name && i->block->bind_point<0 ? i->location : -1;
 }
 
 const Program::AttributeInfo &Program::get_attribute_info(const string &name) const
 {
-       return get_item(attributes, name);
+       vector<AttributeInfo>::const_iterator i = lower_bound(attributes, name, &name_search<AttributeInfo>);
+       if(i==attributes.end() || i->name!=name)
+               throw key_error(name);
+       return *i;
 }
 
 int Program::get_attribute_location(const string &name) const
@@ -604,8 +655,8 @@ int Program::get_attribute_location(const string &name) const
        if(name[name.size()-1]==']')
                throw invalid_argument("Program::get_attribute_location");
 
-       AttributeMap::const_iterator i = attributes.find(name);
-       return i!=attributes.end() ? i->second.location : -1;
+       vector<AttributeInfo>::const_iterator i = lower_bound(attributes, name, &name_search<AttributeInfo>);
+       return i!=attributes.end() && i->name==name ? i->location : -1;
 }
 
 void Program::bind() const
index 48c18d0f56333371130710942a4dbdc9076e9f45..3af4e582f1ba85d7faae39e6331b8b699653542e 100644 (file)
@@ -97,19 +97,15 @@ public:
                AttributeInfo();
        };
 
-       typedef std::map<std::string, UniformInfo> UniformMap;
-       typedef std::map<std::string, UniformBlockInfo> UniformBlockMap;
-       typedef std::map<std::string, AttributeInfo> AttributeMap;
-
 private:
        unsigned id;
        std::vector<unsigned> stage_ids;
        const Module *module;
        bool linked;
-       UniformBlockMap uniform_blocks;
-       UniformMap uniforms;
+       std::vector<UniformBlockInfo> uniform_blocks;
+       std::vector<UniformInfo> uniforms;
        LayoutHash uniform_layout_hash;
-       AttributeMap attributes;
+       std::vector<AttributeInfo> attributes;
 
 public:
        /// Constructs an empty Program with no shader stages attached.
@@ -152,22 +148,25 @@ private:
        void query_uniform_blocks(const std::vector<UniformInfo *> &);
        void query_attributes();
        void collect_uniforms();
-       void collect_block_uniforms(UniformBlockInfo &, const SpirVModule::Structure &, const std::string &, unsigned);
+       void collect_block_uniforms(const SpirVModule::Structure &, const std::string &, unsigned, std::vector<std::string> &);
        void collect_attributes();
        void update_layout_hash();
        static LayoutHash compute_layout_hash(const std::vector<const UniformInfo *> &);
        static bool uniform_location_compare(const UniformInfo *, const UniformInfo *);
+       static bool uniform_name_compare(const UniformInfo &, const UniformInfo &);
+       template<typename T>
+       static bool name_search(const T &, const std::string &);
 public:
        bool is_linked() const { return linked; }
        DEPRECATED std::string get_info_log() const;
 
        LayoutHash get_uniform_layout_hash() const { return uniform_layout_hash; }
-       const UniformBlockMap &get_uniform_blocks() const { return uniform_blocks; }
+       const std::vector<UniformBlockInfo> &get_uniform_blocks() const { return uniform_blocks; }
        const UniformBlockInfo &get_uniform_block_info(const std::string &) const;
-       const UniformMap &get_uniforms() const { return uniforms; }
+       const std::vector<UniformInfo> &get_uniforms() const { return uniforms; }
        const UniformInfo &get_uniform_info(const std::string &) const;
        int get_uniform_location(const std::string &) const;
-       const AttributeMap &get_attributes() const { return attributes; }
+       const std::vector<AttributeInfo> &get_attributes() const { return attributes; }
        const AttributeInfo &get_attribute_info(const std::string &) const;
        int get_attribute_location(const std::string &) const;
 
index b63ad60e3e5138e908ac9781d129ce27f016c144..d6271a733be69ed1f5e8f51e23b25132e80d0560 100644 (file)
@@ -611,7 +611,7 @@ void ProgramData::apply() const
                        dirty = 0;
                }
 
-               const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks();
+               const vector<Program::UniformBlockInfo> &prog_blocks = prog->get_uniform_blocks();
 
                UniformBlock *old_last_block = last_block;
                if(pu.dirty==ALL_ONES)
@@ -622,29 +622,29 @@ void ProgramData::apply() const
                        pu.blocks.reserve(prog_blocks.size());
 
                        pu.used = 0;
-                       for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i)
+                       for(vector<Program::UniformBlockInfo>::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i)
                        {
-                               SharedBlock *shared = get_shared_block(i->second);
+                               SharedBlock *shared = get_shared_block(*i);
                                if(shared)
                                {
                                        if(shared->dirty==ALL_ONES)
-                                               update_block_uniform_indices(*shared, i->second);
+                                               update_block_uniform_indices(*shared, *i);
                                        pu.used |= shared->used;
                                }
 
-                               pu.blocks.push_back(ProgramBlock(i->second.bind_point, shared));
+                               pu.blocks.push_back(ProgramBlock(i->bind_point, shared));
                        }
                }
 
                // Update the contents of all dirty blocks.
                bool buffered_blocks_updated = false;
                std::vector<ProgramBlock>::iterator j = pu.blocks.begin();
-               for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i, ++j)
+               for(vector<Program::UniformBlockInfo>::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i, ++j)
                {
                        if(!j->shared || !j->shared->dirty)
                                continue;
 
-                       update_block(*j->shared, i->second);
+                       update_block(*j->shared, *i);
                        j->shared->dirty = 0;
                        buffered_blocks_updated |= (j->bind_point>=0);
                }