+ const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks();
+
+ if(pu.dirty==ALL_ONES)
+ {
+ /* The set of uniforms has changed since this program was last used.
+ Regenerate the list of uniform blocks. */
+ pu.blocks.clear();
+ pu.blocks.reserve(prog_blocks.size());
+
+ pu.used = 0;
+ for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i)
+ {
+ SharedBlock *shared = get_shared_block(i->second);
+ if(shared)
+ {
+ if(shared->dirty==ALL_ONES)
+ shared->used = compute_slot_mask(i->second);
+ pu.used |= shared->used;
+ }
+
+ pu.blocks.push_back(ProgramBlock(i->second.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)
+ {
+ if(!j->shared || !j->shared->dirty)
+ continue;
+
+ update_block(*j->block, i->second);
+ j->shared->dirty = 0;
+ buffered_blocks_updated |= (j->bind_point>=0);
+ }
+
+ pu.dirty = 0;