ProgramData::ProgramData(const Program *p):
tied_program(p),
+ generation(0),
last_buffer_block(0),
buffer(0),
dirty(0)
ProgramData::ProgramData(const ProgramData &other):
tied_program(other.tied_program),
uniforms(other.uniforms),
+ generation(other.generation),
last_buffer_block(0),
buffer(0),
dirty(0)
return add_uniform(tag, uni);
uniforms[i].replace_value(uni);
- dirty |= 1<<i;
+ mark_dirty(1<<i);
}
template<typename T, typename V>
else
uniforms[i].replace_value(new T(value));
- dirty |= 1<<i;
+ mark_dirty(1<<i);
}
template<typename T, typename V>
else
uniforms[i].replace_value(new UniformArray<T>(n, value));
- dirty |= 1<<i;
+ mark_dirty(1<<i);
}
bool ProgramData::validate_tag(Tag tag) const
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)
delete i->value;
uniforms.erase(i);
- dirty = ALL_ONES;
+ mark_dirty(ALL_ONES);
}
vector<Tag> ProgramData::get_uniform_tags() const
// XXX All these mutables are a bit silly, but I'm out of better ideas
const Program *tied_program;
std::vector<TaggedUniform> uniforms;
+ unsigned generation;
mutable std::vector<SharedBlock> blocks;
mutable std::vector<ProgramBlock> programs;
mutable BufferBackedUniformBlock *last_buffer_block;
void uniform_array(Tag, unsigned, V);
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 remove_uniform(Tag);
+ 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 Renderer::add_shader_data(const ProgramData &d)
{
- if(state->shdata_count<shdata_stack.size() && shdata_stack[state->shdata_count]==&d)
- ++state->shdata_count;
- else
+ if(state->shdata_count<shdata_stack.size())
{
- flush_shader_data();
- shdata_stack.push_back(&d);
- state->shdata_count = shdata_stack.size();
- changed |= SHADER_DATA;
+ const BoundProgramData &top = shdata_stack.back();
+ if(top.shdata==&d && top.generation==d.get_generation())
+ {
+ ++state->shdata_count;
+ return;
+ }
}
+
+ flush_shader_data();
+ shdata_stack.push_back(&d);
+ state->shdata_count = shdata_stack.size();
+ changed |= SHADER_DATA;
}
void Renderer::flush_shader_data()
{
if(extra_shdata)
shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end());
- for(vector<const ProgramData *>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
- (*i)->apply();
+ for(vector<BoundProgramData>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
+ i->shdata->apply();
changed &= ~SHADER_DATA;
}
{ }
+Renderer::BoundProgramData::BoundProgramData(const ProgramData *d):
+ shdata(d),
+ generation(0)
+{ }
+
+
Renderer::State::State():
camera(0),
texture_count(0),
BoundTexture();
};
+ struct BoundProgramData
+ {
+ const ProgramData *shdata;
+ unsigned generation;
+
+ BoundProgramData(const ProgramData *);
+ };
+
struct State
{
const Camera *camera;
State *state;
std::vector<BoundTexture> texture_stack;
ProgramData standard_shdata;
- std::vector<const ProgramData *> shdata_stack;
+ std::vector<BoundProgramData> shdata_stack;
std::set<const Renderable *> excluded;
public: