X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramdata.cpp;h=5f124a907fc8eebbb034d25cddb5ba475c67c022;hp=1e4f5c1d27ceb1e3599079ecd67e455efc387c93;hb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;hpb=8dd40d3723cb2309ffcca5e041898a767cd7cdea diff --git a/source/programdata.cpp b/source/programdata.cpp index 1e4f5c1d..5f124a90 100644 --- a/source/programdata.cpp +++ b/source/programdata.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include "buffer.h" #include "color.h" #include "error.h" @@ -24,7 +26,7 @@ ProgramData::ProgramData(const Program *p): // Blocks are intentionally left uncopied ProgramData::ProgramData(const ProgramData &other): - tied_program(0), + tied_program(other.tied_program), uniforms(other.uniforms), last_block(0), buffer(0), @@ -34,6 +36,23 @@ ProgramData::ProgramData(const ProgramData &other): i->value = i->value->clone(); } +ProgramData::ProgramData(const ProgramData &other, const Program *p): + tied_program(p), + last_block(0), + buffer(0), + dirty(0) +{ + if(tied_program) + { + for(vector::const_iterator i=other.uniforms.begin(); i!=other.uniforms.end(); ++i) + tied_program->get_uniform_info(i->name); + } + + uniforms = other.uniforms; + for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) + i->value = i->value->clone(); +} + ProgramData &ProgramData::operator=(const ProgramData &other) { tied_program = other.tied_program; @@ -70,10 +89,11 @@ void ProgramData::uniform(const string &name, Uniform *uni) { try { - if(tied_program) - tied_program->get_uniform_info(name); - else if(name[name.size()-1]==']') - throw invalid_argument("ProgramData::uniform"); + if(!validate_name(name)) + { + delete uni; + return; + } } catch(...) { @@ -82,16 +102,77 @@ void ProgramData::uniform(const string &name, Uniform *uni) } int i = find_uniform_index(name); - if(i>=0) - { - uniforms[i].replace_value(uni); + if(i<0) + return add_uniform(name, uni); + + uniforms[i].replace_value(uni); + dirty |= 1< +void ProgramData::uniform(const string &name, V value) +{ + if(!validate_name(name)) + return; + + int i = find_uniform_index(name); + if(i<0) + return add_uniform(name, new T(value)); + + if(T *uni = dynamic_cast(uniforms[i].value)) + uni->set(value); + else + uniforms[i].replace_value(new T(value)); - if(static_cast(i) +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(n, value)); + + UniformArray *uni = dynamic_cast *>(uniforms[i].value); + if(uni && n==uni->size()) + uni->set(value); + else + uniforms[i].replace_value(new UniformArray(n, value)); + + dirty |= 1<get_uniform_info(name); + else if(name[name.size()-1]==']') + throw invalid_argument("ProgramData::uniform"); + return true; + } +#ifdef DEBUG + catch(const exception &e) + { + IO::print(IO::cerr, "Error while setting uniform %s: %s: %s\n", name, Debug::demangle(typeid(e).name()), e.what()); + return false; + } +#endif +} + +void ProgramData::add_uniform(const string &name, Uniform *uni) +{ + if(uniforms.size()>=MASK_BITS) + { + delete uni; + throw too_many_uniforms(name); } vector::iterator j = lower_bound(uniforms.begin(), uniforms.end(), name, uniform_name_compare); @@ -111,12 +192,12 @@ void ProgramData::uniform(const string &name, const Uniform &u) void ProgramData::uniform(const string &name, int v) { - uniform(name, new Uniform1i(v)); + uniform(name, v); } void ProgramData::uniform(const string &name, float v) { - uniform(name, new Uniform1f(v)); + uniform(name, v); } void ProgramData::uniform(const string &name, int v0, int v1) @@ -133,12 +214,12 @@ void ProgramData::uniform(const string &name, float v0, float v1) void ProgramData::uniform2(const string &name, const int *v) { - uniform(name, new Uniform2i(v)); + uniform(name, v); } void ProgramData::uniform2(const string &name, const float *v) { - uniform(name, new Uniform2f(v)); + uniform(name, v); } void ProgramData::uniform(const string &name, int v0, int v1, int v2) @@ -160,12 +241,12 @@ void ProgramData::uniform(const string &name, const Vector3 &v) void ProgramData::uniform3(const string &name, const int *v) { - uniform(name, new Uniform3i(v)); + uniform(name, v); } void ProgramData::uniform3(const string &name, const float *v) { - uniform(name, new Uniform3f(v)); + uniform(name, v); } void ProgramData::uniform(const string &name, int v0, int v1, int v2, int v3) @@ -192,12 +273,12 @@ void ProgramData::uniform(const string &name, const Color &c) void ProgramData::uniform4(const string &name, const int *v) { - uniform(name, new Uniform4i(v)); + uniform(name, v); } void ProgramData::uniform4(const string &name, const float *v) { - uniform(name, new Uniform4f(v)); + uniform(name, v); } void ProgramData::uniform(const string &name, const LinAl::Matrix &m) @@ -207,7 +288,37 @@ void ProgramData::uniform(const string &name, const LinAl::Matrix & void ProgramData::uniform_matrix2(const string &name, const float *v) { - uniform(name, new UniformMatrix2x2f(v)); + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix3x2(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix3x2(const string &name, const float *v) +{ + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix4x2(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix4x2(const string &name, const float *v) +{ + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix2x3(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix2x3(const string &name, const float *v) +{ + uniform(name, v); } void ProgramData::uniform(const string &name, const LinAl::Matrix &m) @@ -217,7 +328,37 @@ void ProgramData::uniform(const string &name, const LinAl::Matrix & void ProgramData::uniform_matrix3(const string &name, const float *v) { - uniform(name, new UniformMatrix3x3f(v)); + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix4x3(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix4x3(const string &name, const float *v) +{ + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix2x4(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix2x4(const string &name, const float *v) +{ + uniform(name, v); +} + +void ProgramData::uniform(const string &name, const LinAl::Matrix &m) +{ + uniform_matrix3x4(name, &m(0, 0)); +} + +void ProgramData::uniform_matrix3x4(const string &name, const float *v) +{ + uniform(name, v); } void ProgramData::uniform(const string &name, const Matrix &m) @@ -227,62 +368,92 @@ void ProgramData::uniform(const string &name, const Matrix &m) void ProgramData::uniform_matrix4(const string &name, const float *v) { - uniform(name, new UniformMatrix4x4f(v)); + uniform(name, v); } void ProgramData::uniform1_array(const string &name, unsigned n, const int *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform1_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform2_array(const string &name, unsigned n, const int *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform2_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform3_array(const string &name, unsigned n, const int *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform3_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform4_array(const string &name, unsigned n, const int *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform4_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::uniform_matrix2_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix3x2_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix4x2_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix2x3_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); } void ProgramData::uniform_matrix3_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix4x3_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix2x4_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); +} + +void ProgramData::uniform_matrix3x4_array(const string &name, unsigned n, const float *v) +{ + uniform_array(name, n, v); } void ProgramData::uniform_matrix4_array(const string &name, unsigned n, const float *v) { - uniform(name, new UniformArray(n, v)); + uniform_array(name, n, v); } void ProgramData::remove_uniform(const string &name) @@ -314,6 +485,12 @@ const Uniform &ProgramData::get_uniform(const string &name) const return *uniforms[i].value; } +const Uniform *ProgramData::find_uniform(const string &name) const +{ + int i = find_uniform_index(name); + return (i>=0 ? uniforms[i].value : 0); +} + bool ProgramData::uniform_name_compare(const NamedUniform &nu, const string &name) { return nu.name::const_iterator j=info.uniforms.begin(); (!any_found && j!=info.uniforms.end()); ++j) - any_found = (find_uniform_index((*j)->name)>=0); + bool all_found = true; + for(vector::const_iterator j=info.uniforms.begin(); j!=info.uniforms.end(); ++j) + { + if(find_uniform_index((*j)->name)>=0) + any_found = true; + else + all_found = false; + } - // TODO throw if all uniforms for a buffer-backed block are not found if(!any_found) return 0; + else if(!all_found && info.bind_point>=0) + { +#ifdef DEBUG + IO::print(IO::cerr, "Warning: not all uniforms for block %s are present\n", info.name); +#else + throw incomplete_uniform_block(info.name); +#endif + } UniformBlock *block; if(info.bind_point>=0) { if(!buffer) - { buffer = new Buffer(UNIFORM_BUFFER); - buffer->set_usage(STREAM_DRAW); - } block = new UniformBlock(info.data_size); block->use_buffer(buffer, last_block); @@ -414,7 +601,7 @@ void ProgramData::apply() const { /* If the global dirty flag affects this program, add it to per-program dirty flags and clear the global flag. A previously unseen program will - always cause this to happen. */ + cause this to happen if there's any dirty uniforms. */ if(affected) { for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i) @@ -426,6 +613,7 @@ void ProgramData::apply() const const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks(); + UniformBlock *old_last_block = last_block; if(pu.dirty==ALL_ONES) { /* The set of uniforms has changed since this program was last used. @@ -467,6 +655,22 @@ void ProgramData::apply() const to avoid state thrashing. */ if(buffered_blocks_updated && !ARB_direct_state_access) buffer->bind(); + + if(last_block!=old_last_block) + { + unsigned required_size = last_block->get_required_buffer_size(); + if(last_block->get_required_buffer_size()>buffer->get_size()) + { + if(buffer->get_size()>0) + { + delete buffer; + buffer = new Buffer(UNIFORM_BUFFER); + last_block->change_buffer(buffer); + } + + buffer->storage(required_size); + } + } } for(vector::iterator i=pu.blocks.begin(); i!=pu.blocks.end(); ++i)