]> git.tdb.fi Git - libs/gl.git/commitdiff
Eliminate the polymorphic Uniform class hierarchy
authorMikko Rasa <tdb@tdb.fi>
Tue, 28 Sep 2021 22:49:20 +0000 (01:49 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 28 Sep 2021 22:49:20 +0000 (01:49 +0300)
Dynamically allocating a separate object for every uniform is not very
cache friendly.  ProgramData now stores uniform values in a single memory
block instead.

source/core/datatype.h
source/core/uniform.h [deleted file]
source/core/uniformblock.cpp
source/core/uniformblock.h
source/materials/material.cpp
source/materials/renderpass.cpp
source/materials/technique.cpp
source/render/programdata.cpp
source/render/programdata.h

index a911561358c2c845d529f44e67aa090e49639f77..7188cb5a9c847b37a8f455d682ad660189e131f5 100644 (file)
@@ -141,6 +141,4 @@ void require_type(DataType);
 } // namespace GL
 } // namespace Msp
 
-#include "datatype_backend.h"
-
 #endif
diff --git a/source/core/uniform.h b/source/core/uniform.h
deleted file mode 100644 (file)
index 8cdcdfd..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#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
index f713bd2af5d320541b27f114b9a4cad719528231..8f85b87f0ba1573e8749b7f8c405382da8201360 100644 (file)
@@ -1,3 +1,4 @@
+#include <algorithm>
 #include <msp/gl/extensions/arb_shader_objects.h>
 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
 #include "buffer.h"
@@ -5,10 +6,11 @@
 #include "deviceinfo.h"
 #include "error.h"
 #include "matrix.h"
-#include "uniform.h"
 #include "uniformblock.h"
 #include "vector.h"
 
+using namespace std;
+
 namespace Msp {
 namespace GL {
 
@@ -25,16 +27,64 @@ unsigned UniformBlock::get_alignment() const
        return Limits::get_global().uniform_buffer_alignment;
 }
 
-void UniformBlock::store(const ReflectData::UniformInfo &info, const Uniform &uni)
+void UniformBlock::store(const ReflectData::UniformInfo &info, unsigned array_size, const void *value)
 {
+       array_size = min(array_size, max(info.array_size, 1U));
+
+       char *store_ptr;
+       bool packed;
        if(info.block->bind_point<0)
        {
                if(info.location<0)
                        return;
-               uni.store(info, &data[info.location*16]);
+
+               store_ptr = data.data()+info.location*16;
+               packed = true;
+       }
+       else
+       {
+               store_ptr = data.data()+info.offset;
+               if(array_size!=1 && info.array_stride!=get_type_size(info.type))
+                       packed = false;
+               else if(is_matrix(info.type))
+                       packed = (info.matrix_stride==get_type_size(get_matrix_column_type(info.type)));
+               else
+                       packed = true;
+       }
+
+       const char *value_ptr = static_cast<const char *>(value);
+       if(packed)
+       {
+               const char *data_end = value_ptr+array_size*get_type_size(info.type);
+               copy(value_ptr, data_end, store_ptr);
+       }
+       else if(is_matrix(info.type))
+       {
+               unsigned col_size = get_type_size(get_matrix_column_type(info.type));
+               unsigned cols = get_type_size(info.type)/col_size;
+               for(unsigned i=0; i<array_size; ++i)
+               {
+                       char *elem_ptr = store_ptr;
+                       for(unsigned j=0; j<cols; ++j)
+                       {
+                               copy(value_ptr, value_ptr+col_size, elem_ptr);
+                               value_ptr += col_size;
+                               elem_ptr += info.matrix_stride;
+                       }
+                       store_ptr += info.array_stride;
+               }
        }
        else
-               uni.store(info, &data[info.offset]);
+       {
+               unsigned elem_size = get_type_size(info.type);
+               for(unsigned i=0; i<array_size; ++i)
+               {
+                       copy(value_ptr, value_ptr+elem_size, store_ptr);
+                       value_ptr += elem_size;
+                       store_ptr += info.array_stride;
+               }
+       }
+
        dirty = true;
 }
 
index 9f2a0849e9cca10795c759456dc12fcf6405a386..79e699fd5bbf37c36298596deefccebe3b931ecb 100644 (file)
@@ -34,7 +34,7 @@ private:
        virtual unsigned get_alignment() const;
 
 public:
-       void store(const ReflectData::UniformInfo &, const Uniform &);
+       void store(const ReflectData::UniformInfo &, unsigned, const void *);
 };
 
 } // namespace GL
index 328d89a462ccd4db069499ab45ed5fe2d98d7c35..da229c41d2f7aa638fe3cbf9bc9a447975b24f75 100644 (file)
@@ -5,7 +5,6 @@
 #include "pbrmaterial.h"
 #include "program.h"
 #include "resources.h"
-#include "uniform.h"
 #include "unlitmaterial.h"
 
 using namespace std;
index 63ba695bae7fee718834cf2251863e64c527c8db..499a521f1dc8ff17fb3270cfedfd4a370e90c62a 100644 (file)
@@ -9,7 +9,6 @@
 #include "renderer.h"
 #include "texture.h"
 #include "texture2d.h"
-#include "uniform.h"
 
 using namespace std;
 
index be51b1dabbc207ae4eb0b80bcd5bf8d81822f6a6..e41f0c8ef4919612577fcf34baacced5719044fa 100644 (file)
@@ -83,7 +83,7 @@ bool Technique::replace_uniforms(const ProgramData &shdata)
                        if(!new_shdata)
                                new_shdata = new ProgramData(*kvp.second.get_shader_data());
 
-                       new_shdata->uniform(tag, shdata.get_uniform(t));
+                       new_shdata->copy_uniform(shdata, tag);
                        replaced = true;
                }
 
index 377b5ace09eb9632eadac8410bfa675bd5f9a13f..31fc8fa262949b9b5ea5fa328012525ef6d03833 100644 (file)
@@ -10,7 +10,6 @@
 #include "pipelinestate.h"
 #include "program.h"
 #include "programdata.h"
-#include "uniform.h"
 #include "uniformblock.h"
 #include "vector.h"
 
@@ -31,14 +30,12 @@ ProgramData::ProgramData(const Program *p):
 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),
@@ -53,8 +50,7 @@ ProgramData::ProgramData(const ProgramData &other, const 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)
@@ -62,8 +58,7 @@ 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;
@@ -79,8 +74,6 @@ ProgramData &ProgramData::operator=(const ProgramData &other)
 
 ProgramData::~ProgramData()
 {
-       for(TaggedUniform &u: uniforms)
-               delete u.value;
        for(SharedBlock &b: blocks)
        {
                if(b.indices.type_flag==0xFE)
@@ -90,65 +83,47 @@ ProgramData::~ProgramData()
        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
@@ -174,24 +149,6 @@ 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)
@@ -199,19 +156,14 @@ void ProgramData::mark_dirty(Mask bits)
        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)
@@ -228,12 +180,12 @@ void ProgramData::uniform(Tag tag, float v0, float 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)
@@ -250,12 +202,12 @@ void ProgramData::uniform(Tag tag, float v0, float v1, float 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)
@@ -277,52 +229,52 @@ void ProgramData::uniform(Tag tag, const Color &c)
 
 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)
@@ -332,102 +284,102 @@ 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)
@@ -436,7 +388,10 @@ 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);
@@ -451,18 +406,13 @@ vector<Tag> ProgramData::get_uniform_tags() const
        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
@@ -591,7 +541,10 @@ void ProgramData::update_block(SharedBlock &block, const ReflectData::UniformBlo
                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);
+               }
        }
 }
 
@@ -704,18 +657,12 @@ void ProgramData::set_debug_name(const string &name)
 
 
 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),
index 05e1bedc199eb78e7f29f9a4d6b75df9377505e3..474ca4e8d326d3bebbadb567cea32263175ffc5e 100644 (file)
@@ -8,7 +8,6 @@
 #include "matrix.h"
 #include "reflectdata.h"
 #include "tag.h"
-#include "uniform.h"
 #include "vector.h"
 
 namespace Msp {
@@ -104,11 +103,12 @@ private:
        struct TaggedUniform
        {
                Tag tag;
-               Uniform *value;
+               DataType type;
+               unsigned array_size;
+               unsigned data_offset;
+               unsigned data_size;
 
                TaggedUniform();
-
-               void replace_value(Uniform *);
        };
 
        struct SharedBlock
@@ -154,6 +154,7 @@ private:
        // 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;
@@ -170,16 +171,10 @@ public:
        ~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);
@@ -242,8 +237,7 @@ public:
        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;
@@ -260,19 +254,19 @@ public:
 
 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