X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramdata.cpp;h=cd12c2ca47fbff99cdbfe2578d30ebbd0468d997;hp=9a531be2fecefb28dfb38de3375b8dc00c7f6249;hb=HEAD;hpb=133fe7352831197c9ec59f923c1126651d80edcb diff --git a/source/programdata.cpp b/source/programdata.cpp deleted file mode 100644 index 9a531be2..00000000 --- a/source/programdata.cpp +++ /dev/null @@ -1,688 +0,0 @@ -#include -#include "buffer.h" -#include "color.h" -#include "error.h" -#include "matrix.h" -#include "program.h" -#include "programdata.h" -#include "uniform.h" -#include "uniformblock.h" -#include "vector.h" - -using namespace std; - -namespace Msp { -namespace GL { - -ProgramData::ProgramData(const Program *p): - tied_program(p), - last_block(0), - buffer(0), - dirty(0) -{ } - -// Blocks are intentionally left uncopied -ProgramData::ProgramData(const ProgramData &other): - tied_program(0), - uniform_slots(other.uniform_slots), - uniforms(other.uniforms), - last_block(0), - buffer(0), - dirty(0) -{ - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - *i = (*i)->clone(); -} - -ProgramData &ProgramData::operator=(const ProgramData &other) -{ - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - delete *i; - uniforms.clear(); - - tied_program = other.tied_program; - - uniform_slots = other.uniform_slots; - for(vector::const_iterator i=other.uniforms.begin(); i!=other.uniforms.end(); ++i) - uniforms.push_back((*i)->clone()); - - for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i) - delete i->second.block; - programs.clear(); - - last_block = 0; - buffer = 0; - dirty = 0; - - return *this; -} - -ProgramData::~ProgramData() -{ - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - delete *i; - for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i) - delete i->second.block; - delete buffer; -} - -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"); - } - catch(...) - { - delete uni; - throw; - } - - SlotMap::iterator i = uniform_slots.find(name); - if(i!=uniform_slots.end()) - { - Uniform *&slot = uniforms[i->second]; - /* 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 slot; - slot = uni; - - if(i->secondsecond; - else // Force a full update if the mask isn't wide enough - dirty = ALL_ONES; - } - else - { - uniform_slots[name] = uniforms.size(); - uniforms.push_back(uni); - dirty = ALL_ONES; - } -} - -void ProgramData::uniform(const string &name, const Uniform &u) -{ - uniform(name, u.clone()); -} - -void ProgramData::uniform(const string &name, int v) -{ - uniform(name, new Uniform1i(v)); -} - -void ProgramData::uniform(const string &name, float v) -{ - uniform(name, new Uniform1f(v)); -} - -void ProgramData::uniform(const string &name, int v0, int v1) -{ - int va[2] = { v0, v1 }; - uniform2(name, va); -} - -void ProgramData::uniform(const string &name, float v0, float v1) -{ - float va[2] = { v0, v1 }; - uniform2(name, va); -} - -void ProgramData::uniform2(const string &name, const int *v) -{ - uniform(name, new Uniform2i(v)); -} - -void ProgramData::uniform2(const string &name, const float *v) -{ - uniform(name, new Uniform2f(v)); -} - -void ProgramData::uniform(const string &name, int v0, int v1, int v2) -{ - int va[3] = { v0, v1, v2 }; - uniform3(name, va); -} - -void ProgramData::uniform(const string &name, float v0, float v1, float v2) -{ - float va[3] = { v0, v1, v2 }; - uniform3(name, va); -} - -void ProgramData::uniform(const string &name, const Vector3 &v) -{ - uniform(name, v.x, v.y, v.z); -} - -void ProgramData::uniform3(const string &name, const int *v) -{ - uniform(name, new Uniform3i(v)); -} - -void ProgramData::uniform3(const string &name, const float *v) -{ - uniform(name, new Uniform3f(v)); -} - -void ProgramData::uniform(const string &name, int v0, int v1, int v2, int v3) -{ - int va[4] = { v0, v1, v2, v3 }; - uniform4(name, va); -} - -void ProgramData::uniform(const string &name, float v0, float v1, float v2, float v3) -{ - float va[4] = { v0, v1, v2, v3 }; - uniform4(name, va); -} - -void ProgramData::uniform(const string &name, const Vector4 &v) -{ - uniform(name, v.x, v.y, v.z, v.w); -} - -void ProgramData::uniform(const string &name, const Color &c) -{ - uniform(name, c.r, c.g, c.b, c.a); -} - -void ProgramData::uniform4(const string &name, const int *v) -{ - uniform(name, new Uniform4i(v)); -} - -void ProgramData::uniform4(const string &name, const float *v) -{ - uniform(name, new Uniform4f(v)); -} - -void ProgramData::uniform(const string &name, const LinAl::Matrix &m) -{ - uniform_matrix2(name, &m(0, 0)); -} - -void ProgramData::uniform_matrix2(const string &name, const float *v) -{ - uniform(name, new UniformMatrix2x2f(v)); -} - -void ProgramData::uniform(const string &name, const LinAl::Matrix &m) -{ - uniform_matrix3(name, &m(0, 0)); -} - -void ProgramData::uniform_matrix3(const string &name, const float *v) -{ - uniform(name, new UniformMatrix3x3f(v)); -} - -void ProgramData::uniform(const string &name, const Matrix &m) -{ - uniform_matrix4(name, m.data()); -} - -void ProgramData::uniform_matrix4(const string &name, const float *v) -{ - uniform(name, new UniformMatrix4x4f(v)); -} - -void ProgramData::uniform1_array(const string &name, unsigned n, const int *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform1_array(const string &name, unsigned n, const float *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform2_array(const string &name, unsigned n, const int *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform2_array(const string &name, unsigned n, const float *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform3_array(const string &name, unsigned n, const int *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform3_array(const string &name, unsigned n, const float *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform4_array(const string &name, unsigned n, const int *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform4_array(const string &name, unsigned n, const float *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::uniform_matrix4_array(const string &name, unsigned n, const float *v) -{ - uniform(name, new UniformArray(n, v)); -} - -void ProgramData::remove_uniform(const string &name) -{ - SlotMap::iterator i = uniform_slots.find(name); - if(i!=uniform_slots.end()) - { - vector::iterator j = uniforms.begin()+i->second; - delete *j; - uniforms.erase(j); - - for(SlotMap::iterator k=uniform_slots.begin(); k!=uniform_slots.end(); ++k) - if(k->second>i->second) - --k->second; - - uniform_slots.erase(i); - - dirty = ALL_ONES; - } -} - -unsigned ProgramData::compute_slot_mask(const Program::UniformBlockInfo &block) const -{ - unsigned mask = 0; - for(vector::const_iterator i=block.uniforms.begin(); i!=block.uniforms.end(); ++i) - { - SlotMap::const_iterator j = uniform_slots.find((*i)->name); - /* TODO issue a warning (or even error?) either here or in update_block - if all uniforms for a buffer-backed block are not found */ - if(j!=uniform_slots.end() && j->secondsecond; - } - - return mask; -} - -void ProgramData::update_block(UniformBlock &block, const Program::UniformBlockInfo &info) const -{ - for(vector::const_iterator i=info.uniforms.begin(); i!=info.uniforms.end(); ++i) - { - SlotMap::const_iterator j = uniform_slots.find((*i)->name); - if(j!=uniform_slots.end()) - block.attach(**i, *uniforms[j->second]); - } -} - -ProgramData::SharedBlock *ProgramData::get_shared_block(const Program::UniformBlockInfo &info) const -{ - BlockMap::iterator i = blocks.find(info.layout_hash); - if(i==blocks.end()) - { - unsigned used = compute_slot_mask(info); - if(!used) - return 0; - - 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); - last_block = block; - } - else - block = new UniformBlock; - - i = blocks.insert(BlockMap::value_type(info.layout_hash, SharedBlock(used, block))).first; - } - - return &i->second; -} - -void ProgramData::apply() const -{ - const Program *prog = Program::current(); - if(!prog) - throw invalid_operation("ProgramData::apply"); - - Program::LayoutHash layout = prog->get_uniform_layout_hash(); - ProgramUniforms &pu = programs[layout]; - - Mask force_dirty = (dirty==ALL_ONES ? ALL_ONES : 0U); - Mask affected = (dirty&pu.used) | force_dirty; - if(affected|pu.dirty) - { - /* 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. */ - if(affected) - { - for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i) - i->second.dirty |= (dirty&i->second.used) | force_dirty; - for(ProgramMap::iterator i=programs.begin(); i!=programs.end(); ++i) - i->second.dirty |= (dirty&i->second.used) | force_dirty; - dirty = 0; - } - - const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks(); - - if(pu.dirty==ALL_ONES) - { - /* The set of uniforms has changed since this program was last used. - Regenerate the list of uniform blocks. */ - pu.blocks.clear(); - pu.blocks.reserve(prog_blocks.size()); - - pu.used = 0; - for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i) - { - SharedBlock *shared = get_shared_block(i->second); - if(shared) - { - if(shared->dirty==ALL_ONES) - shared->used = compute_slot_mask(i->second); - pu.used |= shared->used; - } - - pu.blocks.push_back(ProgramBlock(i->second.bind_point, shared)); - } - } - - // Update the contents of all dirty blocks. - bool buffered_blocks_updated = false; - std::vector::iterator j = pu.blocks.begin(); - for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i, ++j) - { - if(!j->shared || !j->shared->dirty) - continue; - - update_block(*j->block, i->second); - j->shared->dirty = 0; - buffered_blocks_updated |= (j->bind_point>=0); - } - - pu.dirty = 0; - - /* If any blocks stored in the buffer were updated, bind the buffer here - to avoid state thrashing. */ - if(buffered_blocks_updated && !ARB_direct_state_access) - buffer->bind(); - } - - for(vector::iterator i=pu.blocks.begin(); i!=pu.blocks.end(); ++i) - if(i->block) - i->block->apply(i->bind_point); -} - - -ProgramData::SharedBlock::SharedBlock(unsigned u, UniformBlock *b): - used(u), - dirty(u), - block(b) -{ } - - -ProgramData::ProgramBlock::ProgramBlock(): - bind_point(-1), - block(0), - shared(0) -{ } - -ProgramData::ProgramBlock::ProgramBlock(int p, SharedBlock *b): - bind_point(p), - block(b ? b->block : 0), - shared(b) -{ } - - -ProgramData::ProgramUniforms::ProgramUniforms(): - used(ALL_ONES), - dirty(ALL_ONES) -{ } - - -ProgramData::Loader::Loader(ProgramData &pd): - DataFile::ObjectLoader(pd) -{ - add("uniform", &Loader::uniform1i); - add("uniform1i", &Loader::uniform1i); - add("uniform", &Loader::uniform1f); - add("uniform1f", &Loader::uniform1f); - add("uniform", &Loader::uniform2i); - add("uniform2i", &Loader::uniform2i); - add("uniform", &Loader::uniform2f); - add("uniform2f", &Loader::uniform2f); - add("uniform", &Loader::uniform3i); - add("uniform3i", &Loader::uniform3i); - add("uniform", &Loader::uniform3f); - add("uniform3f", &Loader::uniform3f); - add("uniform", &Loader::uniform4i); - add("uniform4i", &Loader::uniform4i); - add("uniform", &Loader::uniform4f); - add("uniform4f", &Loader::uniform4f); - add("uniform1i_array", &Loader::uniform1i_array); - add("uniform1f_array", &Loader::uniform1f_array); - add("uniform2f_array", &Loader::uniform2f_array); - add("uniform3f_array", &Loader::uniform3f_array); - add("uniform4f_array", &Loader::uniform4f_array); - add("uniform_array", &Loader::uniform_array); -} - -void ProgramData::Loader::uniform1i(const string &n, int v) -{ - obj.uniform(n, v); -} - -void ProgramData::Loader::uniform1f(const string &n, float v) -{ - obj.uniform(n, v); -} - -void ProgramData::Loader::uniform2i(const string &n, int v0, int v1) -{ - obj.uniform(n, v0, v1); -} - -void ProgramData::Loader::uniform2f(const string &n, float v0, float v1) -{ - obj.uniform(n, v0, v1); -} - -void ProgramData::Loader::uniform3i(const string &n, int v0, int v1, int v2) -{ - obj.uniform(n, v0, v1, v2); -} - -void ProgramData::Loader::uniform3f(const string &n, float v0, float v1, float v2) -{ - obj.uniform(n, v0, v1, v2); -} - -void ProgramData::Loader::uniform4i(const string &n, int v0, int v1, int v2, int v3) -{ - obj.uniform(n, v0, v1, v2, v3); -} - -void ProgramData::Loader::uniform4f(const string &n, float v0, float v1, float v2, float v3) -{ - obj.uniform(n, v0, v1, v2, v3); -} - -void ProgramData::Loader::uniform_array_(const string &n, DataType t, unsigned e) -{ - ArrayLoader ldr(t, e); - load_sub_with(ldr); - unsigned size = ldr.get_size(); - if(!size) - throw logic_error("empty uniform array"); - - DataType type = ldr.get_data_type(); - unsigned elem_size = ldr.get_element_size(); - if(type==INT) - { - const int *data = reinterpret_cast(ldr.get_data()); - if(elem_size==1) - obj.uniform1_array(n, size, data); - else if(elem_size==2) - obj.uniform2_array(n, size, data); - else if(elem_size==3) - obj.uniform3_array(n, size, data); - else if(elem_size==4) - obj.uniform4_array(n, size, data); - else - throw logic_error("unsupported combination of array type and element size"); - } - else if(type==FLOAT) - { - const float *data = reinterpret_cast(ldr.get_data()); - if(elem_size==1) - obj.uniform1_array(n, size, data); - else if(elem_size==2) - obj.uniform2_array(n, size, data); - else if(elem_size==3) - obj.uniform3_array(n, size, data); - else if(elem_size==4) - obj.uniform4_array(n, size, data); - else - throw logic_error("unsupported combination of array type and element size"); - } - else - throw logic_error("unsupported array type"); -} - -void ProgramData::Loader::uniform1i_array(const string &n) -{ - uniform_array_(n, INT, 1); -} - -void ProgramData::Loader::uniform1f_array(const string &n) -{ - uniform_array_(n, FLOAT, 1); -} - -void ProgramData::Loader::uniform2i_array(const string &n) -{ - uniform_array_(n, INT, 2); -} - -void ProgramData::Loader::uniform2f_array(const string &n) -{ - uniform_array_(n, FLOAT, 2); -} - -void ProgramData::Loader::uniform3i_array(const string &n) -{ - uniform_array_(n, INT, 3); -} - -void ProgramData::Loader::uniform3f_array(const string &n) -{ - uniform_array_(n, FLOAT, 3); -} - -void ProgramData::Loader::uniform4i_array(const string &n) -{ - uniform_array_(n, INT, 4); -} - -void ProgramData::Loader::uniform4f_array(const string &n) -{ - uniform_array_(n, FLOAT, 4); -} - -void ProgramData::Loader::uniform_array(const string &n) -{ - uniform_array_(n, static_cast(0), 0); -} - - -ProgramData::ArrayLoader::ArrayLoader(DataType t, unsigned e): - type(t), - element_size(e) -{ - add("uniform", &ArrayLoader::uniform1i); - add("uniform1i", &ArrayLoader::uniform1i); - add("uniform", &ArrayLoader::uniform1f); - add("uniform1f", &ArrayLoader::uniform1f); - add("uniform", &ArrayLoader::uniform2f); - add("uniform2f", &ArrayLoader::uniform2f); - add("uniform", &ArrayLoader::uniform3f); - add("uniform3f", &ArrayLoader::uniform3f); - add("uniform", &ArrayLoader::uniform4f); - add("uniform4f", &ArrayLoader::uniform4f); -} - -void ProgramData::ArrayLoader::uniform(DataType t, unsigned e, const void *v) -{ - if(element_size && (t!=type || e!=element_size)) - throw logic_error("heterogeneous array contents"); - - if(!element_size) - { - type = t; - element_size = e; - } - - const char *cv = reinterpret_cast(v); - data.insert(data.end(), cv, cv+element_size*4); -} - -void ProgramData::ArrayLoader::uniform1i(int v) -{ - uniform(INT, 1, &v); -} - -void ProgramData::ArrayLoader::uniform1f(float v) -{ - uniform(FLOAT, 1, &v); -} - -void ProgramData::ArrayLoader::uniform2i(int v0, int v1) -{ - int va[2] = { v0, v1 }; - uniform(INT, 2, va); -} - -void ProgramData::ArrayLoader::uniform2f(float v0, float v1) -{ - float va[2] = { v0, v1 }; - uniform(FLOAT, 2, va); -} - -void ProgramData::ArrayLoader::uniform3i(int v0, int v1, int v2) -{ - int va[3] = { v0, v1, v2 }; - uniform(INT, 3, va); -} - -void ProgramData::ArrayLoader::uniform3f(float v0, float v1, float v2) -{ - float va[3] = { v0, v1, v2 }; - uniform(FLOAT, 3, va); -} - -void ProgramData::ArrayLoader::uniform4i(int v0, int v1, int v2, int v3) -{ - int va[4] = { v0, v1, v2, v3 }; - uniform(INT, 4, va); -} - -void ProgramData::ArrayLoader::uniform4f(float v0, float v1, float v2, float v3) -{ - float va[4] = { v0, v1, v2, v3 }; - uniform(FLOAT, 4, va); -} - -} // namespace GL -} // namespace Msp