X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Frender%2Fprogramdata.cpp;h=65934d382ae29fad792c0b67031a406658b7b3fb;hb=1b23728908f5ec9beb08b2b70737c3903745fddc;hp=7323df905db7093fcbb5db5572b9b7f7faedb5ca;hpb=ba1427f10d574ff8c4dafc4b8673452b19308ca2;p=libs%2Fgl.git diff --git a/source/render/programdata.cpp b/source/render/programdata.cpp index 7323df90..65934d38 100644 --- a/source/render/programdata.cpp +++ b/source/render/programdata.cpp @@ -7,6 +7,7 @@ #include "color.h" #include "error.h" #include "matrix.h" +#include "pipelinestate.h" #include "program.h" #include "programdata.h" #include "uniform.h" @@ -20,7 +21,8 @@ namespace GL { ProgramData::ProgramData(const Program *p): tied_program(p), - last_block(0), + generation(0), + last_buffer_block(0), buffer(0), dirty(0) { } @@ -29,29 +31,30 @@ ProgramData::ProgramData(const Program *p): ProgramData::ProgramData(const ProgramData &other): tied_program(other.tied_program), uniforms(other.uniforms), - last_block(0), + generation(other.generation), + last_buffer_block(0), buffer(0), dirty(0) { - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - i->value = i->value->clone(); + for(TaggedUniform &u: uniforms) + u.value = u.value->clone(); } ProgramData::ProgramData(const ProgramData &other, const Program *p): tied_program(p), - last_block(0), + last_buffer_block(0), buffer(0), dirty(0) { if(tied_program) { - for(vector::const_iterator i=other.uniforms.begin(); i!=other.uniforms.end(); ++i) - validate_tag(i->tag); + for(const TaggedUniform &u: other.uniforms) + validate_tag(u.tag); } uniforms = other.uniforms; - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - i->value = i->value->clone(); + for(TaggedUniform &u: uniforms) + u.value = u.value->clone(); } ProgramData &ProgramData::operator=(const ProgramData &other) @@ -59,14 +62,15 @@ ProgramData &ProgramData::operator=(const ProgramData &other) tied_program = other.tied_program; uniforms = other.uniforms; - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - i->value = i->value->clone(); + for(TaggedUniform &u: uniforms) + u.value = u.value->clone(); - for(vector::iterator i=blocks.begin(); i!=blocks.end(); ++i) - delete i->block; + for(SharedBlock &b: blocks) + delete b.block; + blocks.clear(); programs.clear(); - last_block = 0; + last_buffer_block = 0; buffer = 0; dirty = 0; @@ -75,13 +79,13 @@ ProgramData &ProgramData::operator=(const ProgramData &other) ProgramData::~ProgramData() { - for(vector::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - delete i->value; - for(vector::iterator i=blocks.begin(); i!=blocks.end(); ++i) + for(TaggedUniform &u: uniforms) + delete u.value; + for(SharedBlock &b: blocks) { - if(i->indices.type_flag==0xFE) - delete[] i->indices.dynamic.values; - delete i->block; + if(b.indices.type_flag==0xFE) + delete[] b.indices.dynamic.values; + delete b.block; } delete buffer; } @@ -107,7 +111,7 @@ void ProgramData::uniform(Tag tag, Uniform *uni) return add_uniform(tag, uni); uniforms[i].replace_value(uni); - dirty |= 1< @@ -125,7 +129,7 @@ void ProgramData::uniform(Tag tag, V value) else uniforms[i].replace_value(new T(value)); - dirty |= 1< @@ -144,7 +148,7 @@ void ProgramData::uniform_array(Tag tag, unsigned n, V value) else uniforms[i].replace_value(new UniformArray(n, value)); - dirty |= 1<get_uniform_info(tag); + { + const ReflectData::UniformInfo &info = tied_program->get_uniform_info(tag); + if(is_image(info.type)) + throw invalid_operation("ProgramData::uniform"); + } return true; } #ifdef DEBUG @@ -174,14 +182,21 @@ void ProgramData::add_uniform(Tag tag, Uniform *uni) throw too_many_uniforms(tag.str()); } - vector::iterator j = lower_bound_member(uniforms, tag, &TaggedUniform::tag); + auto j = lower_bound_member(uniforms, tag, &TaggedUniform::tag); TaggedUniform nu; nu.tag = tag; nu.value = uni; uniforms.insert(j, nu); - dirty = ALL_ONES; + mark_dirty(ALL_ONES); +} + +void ProgramData::mark_dirty(Mask bits) +{ + if(!dirty) + ++generation; + dirty |= bits; } void ProgramData::uniform(Tag tag, const Uniform &u) @@ -233,11 +248,6 @@ void ProgramData::uniform(Tag tag, float v0, float v1, float v2) uniform3(tag, va); } -void ProgramData::uniform(Tag tag, const Vector3 &v) -{ - uniform(tag, v.x, v.y, v.z); -} - void ProgramData::uniform3(Tag tag, const int *v) { uniform(tag, v); @@ -260,11 +270,6 @@ void ProgramData::uniform(Tag tag, float v0, float v1, float v2, float v3) uniform4(tag, va); } -void ProgramData::uniform(Tag tag, const Vector4 &v) -{ - uniform(tag, v.x, v.y, v.z, v.w); -} - void ProgramData::uniform(Tag tag, const Color &c) { uniform(tag, c.r, c.g, c.b, c.a); @@ -280,81 +285,41 @@ void ProgramData::uniform4(Tag tag, const float *v) uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix2(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix2(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix3x2(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix3x2(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix4x2(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix4x2(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix2x3(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix2x3(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix3(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix3(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix4x3(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix4x3(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix2x4(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix2x4(Tag tag, const float *v) { uniform(tag, v); } -void ProgramData::uniform(Tag tag, const LinAl::Matrix &m) -{ - uniform_matrix3x4(tag, &m(0, 0)); -} - void ProgramData::uniform_matrix3x4(Tag tag, const float *v) { uniform(tag, v); @@ -370,6 +335,16 @@ void ProgramData::uniform_matrix4(Tag tag, const float *v) uniform(tag, v); } +void ProgramData::uniform_array(Tag tag, unsigned n, const int *v) +{ + uniform_array(tag, n, v); +} + +void ProgramData::uniform_array(Tag tag, unsigned n, const float *v) +{ + uniform_array(tag, n, v); +} + void ProgramData::uniform1_array(Tag tag, unsigned n, const int *v) { uniform_array(tag, n, v); @@ -457,22 +432,22 @@ void ProgramData::uniform_matrix4_array(Tag tag, unsigned n, const float *v) void ProgramData::remove_uniform(Tag tag) { - vector::const_iterator i = lower_bound_member(uniforms, tag, &TaggedUniform::tag); + auto i = lower_bound_member(uniforms, tag, &TaggedUniform::tag); if(i==uniforms.end() || i->tag!=tag) return; delete i->value; uniforms.erase(i); - dirty = ALL_ONES; + mark_dirty(ALL_ONES); } vector ProgramData::get_uniform_tags() const { vector tags; tags.reserve(uniforms.size()); - for(vector::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - tags.push_back(i->tag); + for(const TaggedUniform &u: uniforms) + tags.push_back(u.tag); return tags; } @@ -492,35 +467,35 @@ const Uniform *ProgramData::find_uniform(Tag tag) const int ProgramData::find_uniform_index(Tag tag) const { - vector::const_iterator i = lower_bound_member(uniforms, tag, &TaggedUniform::tag); + auto i = lower_bound_member(uniforms, tag, &TaggedUniform::tag); return ((i!=uniforms.end() && i->tag==tag) ? i-uniforms.begin() : -1); } vector::iterator ProgramData::get_program(const Program &prog) const { - Program::LayoutHash prog_hash = prog.get_uniform_layout_hash(); - vector::iterator i = lower_bound_member(programs, prog_hash, &ProgramBlock::prog_hash); + ReflectData::LayoutHash prog_hash = prog.get_uniform_layout_hash(); + auto i = lower_bound_member(programs, prog_hash, &ProgramBlock::prog_hash); if(i!=programs.end() && i->prog_hash==prog_hash) return i; - const vector &block_infos = prog.get_uniform_blocks(); + const vector &block_infos = prog.get_uniform_blocks(); unsigned index = i-programs.begin(); programs.insert(i, 1+block_infos.size(), ProgramBlock(prog_hash)); /* Block indices may change if new shared blocks need to be inserted. Store the hashes so they can be matched up later. */ - vector block_hashes; + vector block_hashes; block_hashes.reserve(programs.size()); - for(vector::iterator j=programs.begin(); j!=programs.end(); ++j) - block_hashes.push_back(j->block_index>=0 ? blocks[j->block_index].block_hash : 0); + for(const ProgramBlock &b: programs) + block_hashes.push_back(b.block_index>=0 ? blocks[b.block_index].block_hash : 0); for(unsigned j=0; j::iterator k = lower_bound_member(blocks, info.layout_hash, &SharedBlock::block_hash); + auto k = lower_bound_member(blocks, info.layout_hash, &SharedBlock::block_hash); if(k==blocks.end() || k->block_hash!=info.layout_hash) { k = blocks.insert(k, SharedBlock(info.layout_hash)); @@ -534,7 +509,7 @@ vector::iterator ProgramData::get_program(const Progr unsigned hash = block_hashes[j]; if(hash) { - vector::const_iterator k = lower_bound_member(blocks, hash, &SharedBlock::block_hash); + auto k = lower_bound_member(blocks, hash, &SharedBlock::block_hash); programs[j].block_index = k-blocks.begin(); } else @@ -544,14 +519,14 @@ vector::iterator ProgramData::get_program(const Progr return programs.begin()+index; } -void ProgramData::update_block_uniform_indices(SharedBlock &block, const Program::UniformBlockInfo &info) const +void ProgramData::update_block_uniform_indices(SharedBlock &block, const ReflectData::UniformBlockInfo &info) const { - UInt8 *indices = block.indices.values; + uint8_t *indices = block.indices.values; if(info.uniforms.size()>16) { if(block.indices.type_flag==0xFD) { - block.indices.dynamic.values = new UInt8[info.uniforms.size()]; + block.indices.dynamic.values = new uint8_t[info.uniforms.size()]; block.indices.type_flag = 0xFE; } indices = block.indices.dynamic.values; @@ -592,34 +567,41 @@ void ProgramData::update_block_uniform_indices(SharedBlock &block, const Program if(info.bind_point>=0) { if(!buffer) - buffer = new Buffer(UNIFORM_BUFFER); + { + buffer = new Buffer(); + +#ifdef DEBUG + if(!debug_name.empty()) + buffer->set_debug_name(debug_name); +#endif + } - block.block = new UniformBlock(info.data_size); - block.block->use_buffer(buffer, last_block); - last_block = block.block; + BufferBackedUniformBlock *bb_block = new BufferBackedUniformBlock(info.data_size); + block.block = bb_block; + bb_block->use_buffer(buffer, last_buffer_block); + last_buffer_block = bb_block; } else - block.block = new UniformBlock; + block.block = new DefaultUniformBlock; } } -void ProgramData::update_block(SharedBlock &block, const Program::UniformBlockInfo &info) const +void ProgramData::update_block(SharedBlock &block, const ReflectData::UniformBlockInfo &info) const { - const UInt8 *indices = block.get_uniform_indices(); + const uint8_t *indices = block.get_uniform_indices(); for(unsigned i=0; itype)) + ; // Temporarily ignore deprecated use of sampler uniforms in ProgramData + else if(indices[i]!=0xFF) block.block->attach(*info.uniforms[i], *uniforms[indices[i]].value); + } } -void ProgramData::apply() const +vector::const_iterator ProgramData::prepare_program(const Program &prog) const { - const Program *prog = Program::current(); - if(!prog) - throw invalid_operation("ProgramData::apply"); - - UniformBlock *old_last_block = last_block; - vector::iterator prog_begin = get_program(*prog); - Program::LayoutHash prog_hash = prog->get_uniform_layout_hash(); + BufferBackedUniformBlock *old_last_block = last_buffer_block; + auto prog_begin = get_program(prog); Mask force_dirty = (dirty==ALL_ONES ? ALL_ONES : 0U); Mask affected = (dirty&prog_begin->masks.used) | force_dirty; @@ -630,63 +612,65 @@ void ProgramData::apply() const program will cause this to happen if there's any dirty uniforms. */ if(affected) { - for(vector::iterator i=blocks.begin(); i!=blocks.end(); ++i) - i->dirty |= (dirty&i->used) | force_dirty; - for(vector::iterator i=programs.begin(); i!=programs.end(); ++i) - if(i->block_index<0) - i->masks.dirty |= (dirty&i->masks.used) | force_dirty; + for(SharedBlock &b: blocks) + b.dirty |= (dirty&b.used) | force_dirty; + for(ProgramBlock &b: programs) + if(b.block_index<0) + b.masks.dirty |= (dirty&b.masks.used) | force_dirty; dirty = 0; } - const vector &block_infos = prog->get_uniform_blocks(); + const vector &block_infos = prog.get_uniform_blocks(); if(prog_begin->masks.dirty==ALL_ONES) { /* The set of uniforms has changed since this program was last used. Refresh uniform indices within the program's blocks. */ prog_begin->masks.used = 0; - vector::iterator j = prog_begin+1; - for(vector::const_iterator i=block_infos.begin(); i!=block_infos.end(); ++i, ++j) + auto j = prog_begin+1; + for(const ReflectData::UniformBlockInfo &b: block_infos) { SharedBlock &shared = blocks[j->block_index]; if(shared.dirty==ALL_ONES) - update_block_uniform_indices(shared, *i); + update_block_uniform_indices(shared, b); prog_begin->masks.used |= shared.used; j->block = (shared.used ? shared.block : 0); + ++j; } } // Update the contents of all dirty blocks. bool buffered_blocks_updated = false; - vector::iterator j = prog_begin+1; - for(vector::const_iterator i=block_infos.begin(); i!=block_infos.end(); ++i, ++j) + auto j = prog_begin+1; + for(const ReflectData::UniformBlockInfo &b: block_infos) { SharedBlock &shared = blocks[j->block_index]; if(shared.dirty) { - update_block(shared, *i); + update_block(shared, b); shared.dirty = 0; buffered_blocks_updated |= (j->bind_point>=0); } + ++j; } prog_begin->masks.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(); - - if(last_block!=old_last_block) + if(last_buffer_block!=old_last_block) { - unsigned required_size = last_block->get_required_buffer_size(); - if(last_block->get_required_buffer_size()>buffer->get_size()) + unsigned required_size = last_buffer_block->get_required_buffer_size(); + if(last_buffer_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 = new Buffer(); + last_buffer_block->change_buffer(buffer); + +#ifdef DEBUG + if(!debug_name.empty()) + buffer->set_debug_name(debug_name); +#endif } buffer->storage(required_size); @@ -694,9 +678,36 @@ void ProgramData::apply() const } } - for(vector::iterator i=prog_begin+1; (i!=programs.end() && i->prog_hash==prog_hash); ++i) + return prog_begin; +} + +void ProgramData::apply(const Program &prog, PipelineState &state) const +{ + auto prog_begin = prepare_program(prog); + ReflectData::LayoutHash prog_hash = prog_begin->prog_hash; + for(auto i=prog_begin+1; (i!=programs.end() && i->prog_hash==prog_hash); ++i) if(i->block) - i->block->apply(i->bind_point); + { + if(i->bind_point<0) + state.set_uniforms(static_cast(i->block)); + else + { + const BufferBackedUniformBlock *block = static_cast(i->block); + block->refresh(); + state.set_uniform_block(i->bind_point, block); + } + } +} + +void ProgramData::set_debug_name(const string &name) +{ +#ifdef DEBUG + debug_name = name; + if(buffer) + buffer->set_debug_name(name); +#else + (void)name; +#endif } @@ -714,7 +725,7 @@ void ProgramData::TaggedUniform::replace_value(Uniform *v) } -ProgramData::SharedBlock::SharedBlock(Program::LayoutHash h): +ProgramData::SharedBlock::SharedBlock(ReflectData::LayoutHash h): block_hash(h), used(0), dirty(0), @@ -723,13 +734,13 @@ ProgramData::SharedBlock::SharedBlock(Program::LayoutHash h): indices.type_flag = 0xFD; } -const UInt8 *ProgramData::SharedBlock::get_uniform_indices() const +const uint8_t *ProgramData::SharedBlock::get_uniform_indices() const { return (indices.type_flag==0xFE ? indices.dynamic.values : indices.values); } -ProgramData::ProgramBlock::ProgramBlock(Program::LayoutHash h): +ProgramData::ProgramBlock::ProgramBlock(ReflectData::LayoutHash h): prog_hash(h), bind_point(-1), block_index(-1)