+ if((*i)->interface!=iface)
+ {
+ if(write!=i)
+ *write = *i;
+ ++write;
+ continue;
+ }
+
+ if((*i)->interface=="uniform")
+ {
+ auto j = uniforms.find((*i)->name);
+ if(j!=uniforms.end() && j->second.location>=0)
+ {
+ add_layout_value((*i)->layout, "location", j->second.location);
+ continue;
+ }
+ }
+
+ set<unsigned> &used = used_locations[(*i)->interface];
+
+ unsigned size = LocationCounter().apply(**i);
+ while(1)
+ {
+ int blocking = -1;
+ for(unsigned j=0; j<size; ++j)
+ if(used.count(next+j))
+ blocking = next+j;
+ if(blocking<0)
+ break;
+ next = blocking+1;
+ }
+
+ add_layout_value((*i)->layout, "location", next);
+ if((*i)->interface=="uniform")
+ uniforms[(*i)->name].location = next;
+
+ for(unsigned j=0; j<size; ++j)
+ used.insert(next+j);
+ next += size;
+ }
+
+ unplaced_variables.erase(write, unplaced_variables.end());
+}
+
+void LocationAllocator::bind_uniform(RefPtr<Layout> &layout, const string &name, unsigned range)
+{
+ auto i = uniforms.find(name);
+ if(i!=uniforms.end() && i->second.bind_point>=0)
+ add_layout_value(layout, "binding", i->second.bind_point);
+ else
+ {
+ set<unsigned> &used = used_bindings[0];
+
+ unsigned bind_point = fold32(hash64(name))%range;
+ while(used.count(bind_point))
+ bind_point = (bind_point+1)%range;
+
+ add_layout_value(layout, "binding", bind_point);
+ uniforms[name].bind_point = bind_point;
+ used.insert(bind_point);