+ glGetObjectParameterivARB(id, GL_OBJECT_LINK_STATUS_ARB, &value);
+ if(!(linked = value))
+ throw compile_error(get_info_log());
+
+ glGetObjectParameterivARB(id, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &value);
+ for(int i=0; i<value; ++i)
+ {
+ UniformInfo info;
+ char name[128];
+ int len = 0;
+ glGetActiveUniformARB(id, i, 128, &len, &info.size, &info.type, name);
+ if(len)
+ {
+ info.name = name;
+ info.location = glGetUniformLocationARB(id, name);
+ uniforms[name] = info;
+ }
+ }
+
+ string layout_descriptor;
+ for(map<string, UniformInfo>::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i)
+ if(i->second.location>=0)
+ {
+ if(!layout_descriptor.empty())
+ layout_descriptor += '\n';
+ layout_descriptor += format("%d:%s:%x", i->second.location, i->second.name, i->second.type);
+ }
+ uniform_layout_hash = hash32(layout_descriptor);