From: Mikko Rasa Date: Sun, 26 Aug 2012 13:13:36 +0000 (+0300) Subject: Avoid creating blocks for which there are no uniforms X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=3cdcc7f689b3868dd275774b9bd9adb5c436f244 Avoid creating blocks for which there are no uniforms Since this requires finding the relevant uniforms before the block is created, might as well store the list with the block for faster updates. --- diff --git a/source/programdata.cpp b/source/programdata.cpp index e1b4212e..b8a272c0 100644 --- a/source/programdata.cpp +++ b/source/programdata.cpp @@ -17,7 +17,7 @@ namespace GL { ProgramData::ProgramData(): last_block(0), buffer(0), - modified(false) + changes(NO_CHANGES) { static RequireExtension _ext("GL_ARB_shader_objects"); } @@ -27,7 +27,7 @@ ProgramData::ProgramData(const ProgramData &other): uniforms(other.uniforms), last_block(0), buffer(0), - modified(false) + changes(NO_CHANGES) { for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) i->second = i->second->clone(); @@ -48,11 +48,13 @@ void ProgramData::uniform(const string &name, Uniform *uni) { delete i->second; i->second = uni; + changes = VALUES_CHANGED; } else + { uniforms[name] = uni; - - modified = true; + changes = KEYS_CHANGED; + } } void ProgramData::uniform(const string &name, int v) @@ -150,13 +152,36 @@ void ProgramData::uniform_matrix4_array(const string &name, unsigned n, const fl uniform(name, new UniformArray(n, v)); } -const UniformBlock &ProgramData::get_block(const Program &prog, const Program::UniformBlockInfo *info) const +void ProgramData::find_uniforms_for_block(Block &block, const Program::UniformBlockInfo &info) const { - if(modified) + block.uniforms.clear(); + for(vector::const_iterator i=info.uniforms.begin(); i!=info.uniforms.end(); ++i) + { + // XXX individual array elements + UniformMap::const_iterator j = uniforms.find((*i)->name); + if(j!=uniforms.end()) + block.uniforms[(*i)->location] = &j->second; + } +} + +UniformBlock *ProgramData::create_block(const Program::UniformBlockInfo &info) const +{ + UniformBlock *block = new UniformBlock(info.data_size); + if(!buffer) + buffer = new Buffer(UNIFORM_BUFFER); + block->use_buffer(buffer, last_block); + last_block = block; + return block; +} + +const UniformBlock *ProgramData::get_block(const Program &prog, const Program::UniformBlockInfo *info) const +{ + if(changes) { for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i) - i->second.dirty = true; - modified = false; + if(i->second.changessecond.changes = changes; + changes = NO_CHANGES; } unsigned layout_hash = (info ? info->layout_hash : prog.get_uniform_layout_hash()); @@ -165,30 +190,53 @@ const UniformBlock &ProgramData::get_block(const Program &prog, const Program::U if(i==blocks.end()) { i = blocks.insert(BlockMap::value_type(layout_hash, Block())).first; - i->second.dirty = true; if(info) { - i->second.block = new UniformBlock(info->data_size); - if(!buffer) - buffer = new Buffer(UNIFORM_BUFFER); - i->second.block->use_buffer(buffer, last_block); - last_block = i->second.block; + find_uniforms_for_block(i->second, *info); + + if(!i->second.uniforms.empty()) + { + i->second.block = create_block(*info); + i->second.changes = VALUES_CHANGED; + } } else + { i->second.block = new UniformBlock; + i->second.changes = VALUES_CHANGED; + } } + else if(info && i->second.changes==KEYS_CHANGED) + { + find_uniforms_for_block(i->second, *info); + if(!i->second.uniforms.empty()) + { + if(!i->second.block) + i->second.block = create_block(*info); + i->second.changes = VALUES_CHANGED; + } + else + i->second.changes = NO_CHANGES; + } + + if(!i->second.block) + return 0; UniformBlock &block = *i->second.block; - if(i->second.dirty) + if(i->second.changes) { if(info) { - for(vector::const_iterator j=info->uniforms.begin(); j!=info->uniforms.end(); ++j) + vector::const_iterator j = info->uniforms.begin(); + map::const_iterator k = i->second.uniforms.begin(); + while(j!=info->uniforms.end() && k!=i->second.uniforms.end()) { - // XXX individual array elements - UniformMap::const_iterator k = uniforms.find((*j)->name); - if(k!=uniforms.end()) - block.attach(**j, *k->second); + if(k->first==(*j)->location) + { + block.attach(**j, **k->second); + ++k; + } + ++j; } } else @@ -200,13 +248,13 @@ const UniformBlock &ProgramData::get_block(const Program &prog, const Program::U block.attach(loc, *j->second); } } - i->second.dirty = false; + i->second.changes = NO_CHANGES; } - return block; + return █ } -const UniformBlock &ProgramData::get_block(const Program &prog, const string &name) const +const UniformBlock *ProgramData::get_block(const Program &prog, const string &name) const { if(name.empty()) return get_block(prog, 0); @@ -226,10 +274,8 @@ void ProgramData::apply() const typedef pair ApplyBlock; list apply_blocks; for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i) - { - const UniformBlock &block = get_block(*prog, &i->second); - apply_blocks.push_back(make_pair(&block, i->second.bind_point)); - } + if(const UniformBlock *block = get_block(*prog, &i->second)) + apply_blocks.push_back(make_pair(block, i->second.bind_point)); if(buffer) buffer->bind(); @@ -238,13 +284,13 @@ void ProgramData::apply() const i->first->apply(i->second); } - const UniformBlock &block = get_block(*prog, 0); - block.apply(-1); + if(const UniformBlock *block = get_block(*prog, 0)) + block->apply(-1); } ProgramData::Block::Block(): - dirty(false), + changes(NO_CHANGES), block(0) { } diff --git a/source/programdata.h b/source/programdata.h index 4d80bb77..cf642e61 100644 --- a/source/programdata.h +++ b/source/programdata.h @@ -35,10 +35,18 @@ public: }; private: + enum Changes + { + NO_CHANGES, + VALUES_CHANGED, + KEYS_CHANGED + }; + struct Block { - bool dirty; + Changes changes; UniformBlock *block; + std::map uniforms; Block(); }; @@ -51,7 +59,7 @@ private: mutable BlockMap blocks; mutable UniformBlock *last_block; mutable Buffer *buffer; - mutable bool modified; + mutable Changes changes; ProgramData &operator=(const ProgramData &); public: @@ -82,9 +90,11 @@ public: void uniform_matrix4_array(const std::string &, unsigned, const float *); private: - const UniformBlock &get_block(const Program &, const Program::UniformBlockInfo *) const; + void find_uniforms_for_block(Block &, const Program::UniformBlockInfo &) const; + UniformBlock *create_block(const Program::UniformBlockInfo &) const; + const UniformBlock *get_block(const Program &, const Program::UniformBlockInfo *) const; public: - const UniformBlock &get_block(const Program &, const std::string &) const; + const UniformBlock *get_block(const Program &, const std::string &) const; void apply() const; };