+++ /dev/null
-#ifndef MSP_GL_UNIFORM_H_
-#define MSP_GL_UNIFORM_H_
-
-#include <algorithm>
-#include "reflectdata.h"
-
-namespace Msp {
-namespace GL {
-
-class Uniform
-{
-protected:
- Uniform() { }
-private:
- Uniform(const Uniform &);
- Uniform &operator=(const Uniform &);
-public:
- virtual ~Uniform() { }
-
- virtual void store(const ReflectData::UniformInfo &, void *) const = 0;
- virtual Uniform *clone() const = 0;
-};
-
-
-template<typename T>
-class UniformScalar: public Uniform
-{
-public:
- typedef T BaseType;
- typedef T Type;
-
-private:
- Type value;
-
-public:
- UniformScalar(Type v): value(v) { }
-
- void set(Type v) { value = v; }
-
- Type get() const { return value; }
-
- virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
- { store(info, buffer, &value); }
-
- static void store(const ReflectData::UniformInfo &, void *buffer, const T *value)
- { *reinterpret_cast<T *>(buffer) = *value; }
-
- virtual UniformScalar *clone() const
- { return new UniformScalar(value); }
-};
-
-typedef UniformScalar<int> Uniform1i;
-typedef UniformScalar<float> Uniform1f;
-
-
-template<typename T, unsigned vecsize>
-class UniformVector: public Uniform
-{
-public:
- typedef T BaseType;
- typedef T Type[vecsize];
-
-private:
- Type value;
-
-public:
- UniformVector(const T *vp) { set(vp); }
-
- void set(const T *vp)
- { std::copy(vp, vp+vecsize, value); }
-
- BaseType get(unsigned i) const { return value[i]; }
-
- virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
- { store(info, buffer, value); }
-
- static void store(const ReflectData::UniformInfo &, void *buffer, const T *value)
- { std::copy(value, value+vecsize, reinterpret_cast<T *>(buffer)); }
-
- virtual UniformVector *clone() const
- { return new UniformVector(value); }
-};
-
-typedef UniformVector<int, 2> Uniform2i;
-typedef UniformVector<float, 2> Uniform2f;
-typedef UniformVector<int, 3> Uniform3i;
-typedef UniformVector<float, 3> Uniform3f;
-typedef UniformVector<int, 4> Uniform4i;
-typedef UniformVector<float, 4> Uniform4f;
-
-
-template<typename T, unsigned rows, unsigned cols>
-class UniformMatrix: public Uniform
-{
-public:
- typedef T BaseType;
- typedef T Type[rows*cols];
-
-private:
- Type value;
-
-public:
- UniformMatrix(const T *vp) { set(vp); }
-
- void set(const T *vp)
- { std::copy(vp, vp+rows*cols, value); }
-
- virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
- { store(info, buffer, value); }
-
- static void store(const ReflectData::UniformInfo &info, void *buffer, const T *value)
- {
- for(unsigned i=0; i<cols; ++i)
- UniformVector<T, rows>::store(info, reinterpret_cast<char *>(buffer)+i*info.matrix_stride, value+i*rows);
- }
-
- virtual UniformMatrix *clone() const
- { return new UniformMatrix(value); }
-};
-
-// The naming of these types follows the OpenGL convention of columns x rows
-typedef UniformMatrix<float, 2, 2> UniformMatrix2x2f;
-typedef UniformMatrix<float, 2, 3> UniformMatrix3x2f;
-typedef UniformMatrix<float, 2, 4> UniformMatrix4x2f;
-typedef UniformMatrix<float, 3, 2> UniformMatrix2x3f;
-typedef UniformMatrix<float, 3, 3> UniformMatrix3x3f;
-typedef UniformMatrix<float, 3, 4> UniformMatrix4x3f;
-typedef UniformMatrix<float, 4, 2> UniformMatrix2x4f;
-typedef UniformMatrix<float, 4, 3> UniformMatrix3x4f;
-typedef UniformMatrix<float, 4, 4> UniformMatrix4x4f;
-
-
-template<typename T>
-class UniformArray: public Uniform
-{
-private:
- typedef typename T::BaseType BaseType;
- enum { elemsize = sizeof(typename T::Type)/sizeof(typename T::BaseType) };
-
- unsigned size_;
- BaseType *values;
-
-public:
- UniformArray(unsigned n, const BaseType *vp):
- size_(n),
- values(new BaseType[elemsize*size_])
- {
- set(vp);
- }
-
- ~UniformArray()
- {
- delete[] values;
- }
-
- unsigned size() const { return size_; }
-
- void set(const BaseType *vp)
- { std::copy(vp, vp+elemsize*size_, values); }
-
- virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
- {
- for(unsigned i=0; i<size_; ++i)
- T::store(info, reinterpret_cast<char *>(buffer)+i*info.array_stride, values+i*elemsize);
- }
-
- virtual UniformArray *clone() const
- { return new UniformArray(size_, values); }
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
#include "pipelinestate.h"
#include "program.h"
#include "programdata.h"
-#include "uniform.h"
#include "uniformblock.h"
#include "vector.h"
ProgramData::ProgramData(const ProgramData &other):
tied_program(other.tied_program),
uniforms(other.uniforms),
+ uniform_data(other.uniform_data),
generation(other.generation),
last_buffer_block(0),
buffer(0),
dirty(0)
-{
- for(TaggedUniform &u: uniforms)
- u.value = u.value->clone();
-}
+{ }
ProgramData::ProgramData(const ProgramData &other, const Program *p):
tied_program(p),
}
uniforms = other.uniforms;
- for(TaggedUniform &u: uniforms)
- u.value = u.value->clone();
+ uniform_data = other.uniform_data;
}
ProgramData &ProgramData::operator=(const ProgramData &other)
tied_program = other.tied_program;
uniforms = other.uniforms;
- for(TaggedUniform &u: uniforms)
- u.value = u.value->clone();
+ uniform_data = other.uniform_data;
for(SharedBlock &b: blocks)
delete b.block;
ProgramData::~ProgramData()
{
- for(TaggedUniform &u: uniforms)
- delete u.value;
for(SharedBlock &b: blocks)
{
if(b.indices.type_flag==0xFE)
delete buffer;
}
-void ProgramData::uniform(Tag tag, Uniform *uni)
+void ProgramData::uniform(Tag tag, DataType type, unsigned array_size, const void *value)
{
- try
+ if(!validate_tag(tag))
+ return;
+
+ auto i = lower_bound_member(uniforms, tag, &TaggedUniform::tag);
+ if(i==uniforms.end() || i->tag!=tag)
{
- if(!validate_tag(tag))
- {
- delete uni;
- return;
- }
+ if(uniforms.size()>=MASK_BITS)
+ throw too_many_uniforms(tag.str());
+
+ TaggedUniform tu;
+ tu.tag = tag;
+ tu.type = type;
+ tu.array_size = array_size;
+ tu.data_offset = uniform_data.size();
+ tu.data_size = array_size*get_type_size(type);
+ i = uniforms.insert(i, tu);
+ uniform_data.resize(tu.data_offset+tu.data_size);
+
+ mark_dirty(ALL_ONES);
}
- catch(...)
+ else if(type!=i->type)
+ throw invalid_operation("ProgramData::uniform");
+ else if(array_size>i->array_size)
{
- delete uni;
- throw;
+ unsigned add_bytes = (array_size-i->array_size)*get_type_size(type);
+ uniform_data.insert(uniform_data.begin()+i->data_offset+i->data_size, add_bytes, 0);
+ for(TaggedUniform &u: uniforms)
+ if(u.data_offset>i->data_offset)
+ u.data_offset += add_bytes;
+ i->array_size = array_size;
+ i->data_size = array_size*get_type_size(type);
}
- int i = find_uniform_index(tag);
- if(i<0)
- return add_uniform(tag, uni);
-
- uniforms[i].replace_value(uni);
- mark_dirty(1<<i);
-}
-
-template<typename T, typename V>
-void ProgramData::uniform(Tag tag, V value)
-{
- if(!validate_tag(tag))
- return;
+ const char *val_begin = static_cast<const char *>(value);
+ const char *val_end = val_begin+array_size*get_type_size(type);
+ char *store_begin = uniform_data.data()+i->data_offset;
+ copy(val_begin, val_end, store_begin);
- int i = find_uniform_index(tag);
- if(i<0)
- return add_uniform(tag, new T(value));
-
- if(T *uni = dynamic_cast<T *>(uniforms[i].value))
- uni->set(value);
- else
- uniforms[i].replace_value(new T(value));
-
- mark_dirty(1<<i);
-}
-
-template<typename T, typename V>
-void ProgramData::uniform_array(Tag tag, unsigned n, V value)
-{
- if(!validate_tag(tag))
- return;
-
- int i = find_uniform_index(tag);
- if(i<0)
- return add_uniform(tag, 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));
-
- mark_dirty(1<<i);
+ mark_dirty(1<<(i-uniforms.begin()));
}
bool ProgramData::validate_tag(Tag tag) const
#endif
}
-void ProgramData::add_uniform(Tag tag, Uniform *uni)
-{
- if(uniforms.size()>=MASK_BITS)
- {
- delete uni;
- throw too_many_uniforms(tag.str());
- }
-
- auto j = lower_bound_member(uniforms, tag, &TaggedUniform::tag);
-
- TaggedUniform nu;
- nu.tag = tag;
- nu.value = uni;
- uniforms.insert(j, nu);
-
- mark_dirty(ALL_ONES);
-}
-
void ProgramData::mark_dirty(Mask bits)
{
if(!dirty)
dirty |= bits;
}
-void ProgramData::uniform(Tag tag, const Uniform &u)
-{
- uniform(tag, u.clone());
-}
-
void ProgramData::uniform(Tag tag, int v)
{
- uniform<Uniform1i>(tag, v);
+ uniform(tag, INT, 1, &v);
}
void ProgramData::uniform(Tag tag, float v)
{
- uniform<Uniform1f>(tag, v);
+ uniform(tag, FLOAT, 1, &v);
}
void ProgramData::uniform(Tag tag, int v0, int v1)
void ProgramData::uniform2(Tag tag, const int *v)
{
- uniform<Uniform2i>(tag, v);
+ uniform(tag, INT_VEC2, 1, v);
}
void ProgramData::uniform2(Tag tag, const float *v)
{
- uniform<Uniform2f>(tag, v);
+ uniform(tag, FLOAT_VEC2, 1, v);
}
void ProgramData::uniform(Tag tag, int v0, int v1, int v2)
void ProgramData::uniform3(Tag tag, const int *v)
{
- uniform<Uniform3i>(tag, v);
+ uniform(tag, INT_VEC3, 1, v);
}
void ProgramData::uniform3(Tag tag, const float *v)
{
- uniform<Uniform3f>(tag, v);
+ uniform(tag, FLOAT_VEC3, 1, v);
}
void ProgramData::uniform(Tag tag, int v0, int v1, int v2, int v3)
void ProgramData::uniform4(Tag tag, const int *v)
{
- uniform<Uniform4i>(tag, v);
+ uniform(tag, INT_VEC4, 1, v);
}
void ProgramData::uniform4(Tag tag, const float *v)
{
- uniform<Uniform4f>(tag, v);
+ uniform(tag, FLOAT_VEC4, 1, v);
}
void ProgramData::uniform_matrix2(Tag tag, const float *v)
{
- uniform<UniformMatrix2x2f>(tag, v);
+ uniform(tag, FLOAT_MAT2, 1, v);
}
void ProgramData::uniform_matrix3x2(Tag tag, const float *v)
{
- uniform<UniformMatrix3x2f>(tag, v);
+ uniform(tag, FLOAT_MAT3x2, 1, v);
}
void ProgramData::uniform_matrix4x2(Tag tag, const float *v)
{
- uniform<UniformMatrix4x2f>(tag, v);
+ uniform(tag, FLOAT_MAT4x2, 1, v);
}
void ProgramData::uniform_matrix2x3(Tag tag, const float *v)
{
- uniform<UniformMatrix2x3f>(tag, v);
+ uniform(tag, FLOAT_MAT2x3, 1, v);
}
void ProgramData::uniform_matrix3(Tag tag, const float *v)
{
- uniform<UniformMatrix3x3f>(tag, v);
+ uniform(tag, FLOAT_MAT3, 1, v);
}
void ProgramData::uniform_matrix4x3(Tag tag, const float *v)
{
- uniform<UniformMatrix4x3f>(tag, v);
+ uniform(tag, FLOAT_MAT4x3, 1, v);
}
void ProgramData::uniform_matrix2x4(Tag tag, const float *v)
{
- uniform<UniformMatrix2x4f>(tag, v);
+ uniform(tag, FLOAT_MAT2x4, 1, v);
}
void ProgramData::uniform_matrix3x4(Tag tag, const float *v)
{
- uniform<UniformMatrix3x4f>(tag, v);
+ uniform(tag, FLOAT_MAT3x4, 1, v);
}
void ProgramData::uniform(Tag tag, const Matrix &m)
void ProgramData::uniform_matrix4(Tag tag, const float *v)
{
- uniform<UniformMatrix4x4f>(tag, v);
+ uniform(tag, FLOAT_MAT4, 1, v);
}
void ProgramData::uniform_array(Tag tag, unsigned n, const int *v)
{
- uniform_array<Uniform1i>(tag, n, v);
+ uniform(tag, INT, n, v);
}
void ProgramData::uniform_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<Uniform1f>(tag, n, v);
+ uniform(tag, FLOAT, n, v);
}
void ProgramData::uniform1_array(Tag tag, unsigned n, const int *v)
{
- uniform_array<Uniform1i>(tag, n, v);
+ uniform(tag, INT, n, v);
}
void ProgramData::uniform1_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<Uniform1f>(tag, n, v);
+ uniform(tag, FLOAT, n, v);
}
void ProgramData::uniform2_array(Tag tag, unsigned n, const int *v)
{
- uniform_array<Uniform2i>(tag, n, v);
+ uniform(tag, INT_VEC2, n, v);
}
void ProgramData::uniform2_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<Uniform2f>(tag, n, v);
+ uniform(tag, FLOAT_VEC2, n, v);
}
void ProgramData::uniform3_array(Tag tag, unsigned n, const int *v)
{
- uniform_array<Uniform3i>(tag, n, v);
+ uniform(tag, INT_VEC3, n, v);
}
void ProgramData::uniform3_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<Uniform3f>(tag, n, v);
+ uniform(tag, FLOAT_VEC3, n, v);
}
void ProgramData::uniform4_array(Tag tag, unsigned n, const int *v)
{
- uniform_array<Uniform4i>(tag, n, v);
+ uniform(tag, INT_VEC4, n, v);
}
void ProgramData::uniform4_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<Uniform4f>(tag, n, v);
+ uniform(tag, FLOAT_VEC4, n, v);
}
void ProgramData::uniform_matrix2_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix2x2f>(tag, n, v);
+ uniform(tag, FLOAT_MAT2, n, v);
}
void ProgramData::uniform_matrix3x2_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix3x2f>(tag, n, v);
+ uniform(tag, FLOAT_MAT3x2, n, v);
}
void ProgramData::uniform_matrix4x2_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix4x2f>(tag, n, v);
+ uniform(tag, FLOAT_MAT4x2, n, v);
}
void ProgramData::uniform_matrix2x3_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix2x3f>(tag, n, v);
+ uniform(tag, FLOAT_MAT2x3, n, v);
}
void ProgramData::uniform_matrix3_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix3x3f>(tag, n, v);
+ uniform(tag, FLOAT_MAT3, n, v);
}
void ProgramData::uniform_matrix4x3_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix4x3f>(tag, n, v);
+ uniform(tag, FLOAT_MAT4x3, n, v);
}
void ProgramData::uniform_matrix2x4_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix2x4f>(tag, n, v);
+ uniform(tag, FLOAT_MAT2x4, n, v);
}
void ProgramData::uniform_matrix3x4_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix3x4f>(tag, n, v);
+ uniform(tag, FLOAT_MAT3x4, n, v);
}
void ProgramData::uniform_matrix4_array(Tag tag, unsigned n, const float *v)
{
- uniform_array<UniformMatrix4x4f>(tag, n, v);
+ uniform(tag, FLOAT_MAT4, n, v);
}
void ProgramData::remove_uniform(Tag tag)
if(i==uniforms.end() || i->tag!=tag)
return;
- delete i->value;
+ uniform_data.erase(uniform_data.begin()+i->data_offset, uniform_data.begin()+i->data_offset+i->data_size);
+ for(TaggedUniform &u: uniforms)
+ if(u.data_offset>i->data_offset)
+ u.data_offset -= i->data_size;
uniforms.erase(i);
mark_dirty(ALL_ONES);
return tags;
}
-const Uniform &ProgramData::get_uniform(Tag tag) const
+void ProgramData::copy_uniform(const ProgramData &source, Tag tag)
{
- int i = find_uniform_index(tag);
+ int i = source.find_uniform_index(tag);
if(i<0)
throw key_error(tag);
- return *uniforms[i].value;
-}
-
-const Uniform *ProgramData::find_uniform(Tag tag) const
-{
- int i = find_uniform_index(tag);
- return (i>=0 ? uniforms[i].value : 0);
+ const TaggedUniform &tu = source.uniforms[i];
+ uniform(tag, tu.type, tu.array_size, source.uniform_data.data()+tu.data_offset);
}
int ProgramData::find_uniform_index(Tag tag) const
if(is_image(info.uniforms[i]->type))
; // Temporarily ignore deprecated use of sampler uniforms in ProgramData
else if(indices[i]!=0xFF)
- block.block->store(*info.uniforms[i], *uniforms[indices[i]].value);
+ {
+ const TaggedUniform &tu = uniforms[indices[i]];
+ block.block->store(*info.uniforms[i], tu.array_size, uniform_data.data()+tu.data_offset);
+ }
}
}
ProgramData::TaggedUniform::TaggedUniform():
- value(0)
+ type(VOID),
+ array_size(0),
+ data_offset(0),
+ data_size(0)
{ }
-void ProgramData::TaggedUniform::replace_value(Uniform *v)
-{
- /* UniformBlock does not copy the uniforms, so existing default blocks
- will be left with stale pointers. This is not a problem as long as no
- one stores pointers to the blocks and expects them to stay valid. */
- delete value;
- value = v;
-}
-
ProgramData::SharedBlock::SharedBlock(ReflectData::LayoutHash h):
block_hash(h),
#include "matrix.h"
#include "reflectdata.h"
#include "tag.h"
-#include "uniform.h"
#include "vector.h"
namespace Msp {
struct TaggedUniform
{
Tag tag;
- Uniform *value;
+ DataType type;
+ unsigned array_size;
+ unsigned data_offset;
+ unsigned data_size;
TaggedUniform();
-
- void replace_value(Uniform *);
};
struct SharedBlock
// XXX All these mutables are a bit silly, but I'm out of better ideas
const Program *tied_program;
std::vector<TaggedUniform> uniforms;
+ std::vector<char> uniform_data;
unsigned generation;
mutable std::vector<SharedBlock> blocks;
mutable std::vector<ProgramBlock> programs;
~ProgramData();
private:
- void uniform(Tag, Uniform *);
- template<typename T, typename V>
- void uniform(Tag, V);
- template<typename T, typename V>
- void uniform_array(Tag, unsigned, V);
+ void uniform(Tag, DataType, unsigned, const void *);
bool validate_tag(Tag) const;
- void add_uniform(Tag, Uniform *);
void mark_dirty(Mask);
public:
- void uniform(Tag, const Uniform &);
void uniform(Tag, int);
void uniform(Tag, float);
void uniform(Tag, int, int);
unsigned get_generation() const { return generation; }
std::vector<Tag> get_uniform_tags() const;
- const Uniform &get_uniform(Tag) const;
- const Uniform *find_uniform(Tag) const;
+ void copy_uniform(const ProgramData &, Tag);
private:
int find_uniform_index(Tag) const;
template<typename T, unsigned N>
void ProgramData::uniform(Tag tag, const LinAl::Vector<T, N> &v)
-{ uniform<UniformVector<T, N> >(tag, &v.x); }
+{ uniform(tag, TypeTraits<LinAl::Vector<T, N>>::type, 1, &v.x); }
template<typename T, unsigned R, unsigned C>
void ProgramData::uniform(Tag tag, const LinAl::Matrix<T, R, C> &v)
-{ uniform<UniformMatrix<T, R, C> >(tag, &v(0, 0)); }
+{ uniform(tag, TypeTraits<LinAl::Matrix<T, R, C>>::type, 1, &v(0, 0)); }
template<typename T, unsigned N>
void ProgramData::uniform_array(Tag tag, unsigned n, const LinAl::Vector<T, N> *v)
-{ uniform_array<UniformVector<T, N> >(tag, n, &v[0].x); }
+{ uniform(tag, TypeTraits<LinAl::Vector<T, N>>::type, n, &v[0].x); }
template<typename T, unsigned R, unsigned C>
void ProgramData::uniform_array(Tag tag, unsigned n, const LinAl::Matrix<T, R, C> *v)
-{ uniform_array<UniformMatrix<T, R, C> >(tag, n, &v[0](0, 0)); }
+{ uniform(tag, TypeTraits<LinAl::Matrix<T, R, C>>::type, n, &v[0](0, 0)); }
} // namespace GL
} // namespace Msp