+
+ int i = find_uniform_index(name);
+ if(i<0)
+ return add_uniform(name, new T(value));
+
+ if(T *uni = dynamic_cast<T *>(uniforms[i].value))
+ uni->set(value);
+ else
+ uniforms[i].replace_value(new T(value));
+
+ dirty |= 1<<i;
+}
+
+template<typename T, typename V>
+void ProgramData::uniform_array(const string &name, unsigned n, V value)
+{
+ if(!validate_name(name))
+ return;
+
+ int i = find_uniform_index(name);
+ if(i<0)
+ return add_uniform(name, new UniformArray<T>(n, value));
+
+ UniformArray<T> *uni = dynamic_cast<UniformArray<T> *>(uniforms[i].value);
+ if(uni && n==uni->size())
+ uni->set(value);
+ else
+ uniforms[i].replace_value(new UniformArray<T>(n, value));
+
+ dirty |= 1<<i;
+}
+
+bool ProgramData::validate_name(const string &name) const
+{
+#ifdef DEBUG
+ try
+#endif
+ {
+ if(tied_program)
+ tied_program->get_uniform_info(name);
+ else if(name[name.size()-1]==']')
+ throw invalid_argument("ProgramData::uniform");
+ return true;