]> git.tdb.fi Git - libs/gl.git/commitdiff
Use a generation number to track if ProgramData has changed
authorMikko Rasa <tdb@tdb.fi>
Wed, 21 Apr 2021 14:06:18 +0000 (17:06 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 21 Apr 2021 14:06:18 +0000 (17:06 +0300)
This avoids the need for an application to call flush_shader_data after
a change to uniform values in some cases.

source/render/programdata.cpp
source/render/programdata.h
source/render/renderer.cpp
source/render/renderer.h

index d934b48782c23ce181a5022b5fcfeb6009ad83b4..f3c6108c767284a9e158ee88df7fdd9a5986873d 100644 (file)
@@ -20,6 +20,7 @@ namespace GL {
 
 ProgramData::ProgramData(const Program *p):
        tied_program(p),
+       generation(0),
        last_buffer_block(0),
        buffer(0),
        dirty(0)
@@ -29,6 +30,7 @@ ProgramData::ProgramData(const Program *p):
 ProgramData::ProgramData(const ProgramData &other):
        tied_program(other.tied_program),
        uniforms(other.uniforms),
+       generation(other.generation),
        last_buffer_block(0),
        buffer(0),
        dirty(0)
@@ -107,7 +109,7 @@ void ProgramData::uniform(Tag tag, Uniform *uni)
                return add_uniform(tag, uni);
 
        uniforms[i].replace_value(uni);
-       dirty |= 1<<i;
+       mark_dirty(1<<i);
 }
 
 template<typename T, typename V>
@@ -125,7 +127,7 @@ void ProgramData::uniform(Tag tag, V value)
        else
                uniforms[i].replace_value(new T(value));
 
-       dirty |= 1<<i;
+       mark_dirty(1<<i);
 }
 
 template<typename T, typename V>
@@ -144,7 +146,7 @@ void ProgramData::uniform_array(Tag tag, unsigned n, V value)
        else
                uniforms[i].replace_value(new UniformArray<T>(n, value));
 
-       dirty |= 1<<i;
+       mark_dirty(1<<i);
 }
 
 bool ProgramData::validate_tag(Tag tag) const
@@ -185,7 +187,14 @@ void ProgramData::add_uniform(Tag tag, Uniform *uni)
        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)
@@ -428,7 +437,7 @@ void ProgramData::remove_uniform(Tag tag)
        delete i->value;
        uniforms.erase(i);
 
-       dirty = ALL_ONES;
+       mark_dirty(ALL_ONES);
 }
 
 vector<Tag> ProgramData::get_uniform_tags() const
index f600f02585c3d13fcd5cdd57ba0004da30c2e04b..aeffae45700726f9bc5bd9c7fbc350477486eb90 100644 (file)
@@ -152,6 +152,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;
+       unsigned generation;
        mutable std::vector<SharedBlock> blocks;
        mutable std::vector<ProgramBlock> programs;
        mutable BufferBackedUniformBlock *last_buffer_block;
@@ -173,6 +174,7 @@ private:
        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);
@@ -234,6 +236,8 @@ public:
 
        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;
index 15e4437ffe962c479f082487d5875299b3939d2a..8e8e215f4237fe48444b3a98e257c1d331413e7d 100644 (file)
@@ -187,15 +187,20 @@ void Renderer::set_shader_program(const Program *p, const ProgramData *d)
 
 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()
@@ -392,8 +397,8 @@ void Renderer::apply_state()
        {
                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;
        }
 
@@ -422,6 +427,12 @@ Renderer::BoundTexture::BoundTexture():
 { }
 
 
+Renderer::BoundProgramData::BoundProgramData(const ProgramData *d):
+       shdata(d),
+       generation(0)
+{ }
+
+
 Renderer::State::State():
        camera(0),
        texture_count(0),
index 603866073c7e81f6edac092d6db169d7c7a98051..89f111221c0ce2d482363956e18f3578331a72a0 100644 (file)
@@ -75,6 +75,14 @@ private:
                BoundTexture();
        };
 
+       struct BoundProgramData
+       {
+               const ProgramData *shdata;
+               unsigned generation;
+
+               BoundProgramData(const ProgramData *);
+       };
+
        struct State
        {
                const Camera *camera;
@@ -110,7 +118,7 @@ private:
        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: