]> git.tdb.fi Git - libs/gl.git/commitdiff
State management improvements in Renderer
authorMikko Rasa <tdb@tdb.fi>
Thu, 30 Oct 2014 08:21:18 +0000 (10:21 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 30 Oct 2014 08:24:33 +0000 (10:24 +0200)
Only update modelview matrix in standard_shdata if it actually changed.

Don't re-apply all shader data unless the program changed.

React to lighting changes caused by pop_state.

source/renderer.cpp
source/renderer.h

index 54d12051c9945066badc10231685e43398aad0f1..2f253e2ab8c4f96471d3bf8e1491e450910f4bef 100644 (file)
@@ -24,6 +24,7 @@ Renderer::Renderer(const Camera *c):
        mtx_stack(*this),
        changed(MATRIX),
        matrices_loaded(false),
+       shdata_applied(0),
        camera(c),
        state_stack(1),
        element_buffer(0)
@@ -85,10 +86,6 @@ void Renderer::set_shader_program(const Program *p, const ProgramData *d)
        state->shprog = p;
        if(p && d)
                add_shader_data(*d);
-
-       /* Even if we have no new shdata, the existing ones need to be re-applied
-       to the new program */
-       shdata_changed = true;
 }
 
 void Renderer::add_shader_data(const ProgramData &d)
@@ -130,12 +127,23 @@ void Renderer::pop_state()
        if(state_stack.size()==1)
                throw stack_underflow("Renderer::pop_state");
 
+       const Lighting *old_lighting = state->lighting;
        state_stack.pop_back();
        state = &state_stack.back();
        if(shdata_stack.size()>state->shdata_count)
+       {
                shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end());
+               changed |= SHADER_DATA;
+       }
+       shdata_applied = min<unsigned>(shdata_applied, shdata_stack.size());
        mtx_stack.pop();
-       changed |= MATRIX|SHADER_DATA;
+       changed |= MATRIX;
+       if(state->lighting!=old_lighting)
+       {
+               if(state->lighting)
+                       state->lighting->update_shader_data(standard_shdata, state->lighting_matrix);
+               changed |= LIGHTING;
+       }
 }
 
 void Renderer::escape()
@@ -233,7 +241,7 @@ void Renderer::apply_state()
                        {
                                MatrixStack::modelview() = state->lighting_matrix;
                                state->lighting->bind();
-                               changed = (changed&~LIGHTING)|MATRIX;
+                               changed = (changed&~LIGHTING)|LEGACY_MATRIX;
                        }
                        else
                                Lighting::unbind();
@@ -242,28 +250,38 @@ void Renderer::apply_state()
 
        if(state->shprog)
        {
+               bool shprog_changed = (state->shprog!=Program::current());
                state->shprog->bind();
 
                if(!legacy_bindings)
                {
-                       const Matrix &m = mtx_stack.top();
-                       standard_shdata.uniform("eye_obj_matrix", mtx_stack.top());
-                       LinAl::SquareMatrix<float, 3> nm;
-                       for(unsigned i=0; i<3; ++i)
-                               for(unsigned j=0; j<3; ++j)
-                                       nm(i, j) = m(i, j);
-                       nm = transpose(invert(nm));
-                       standard_shdata.uniform_matrix3("eye_obj_normal_matrix", &nm(0, 0));
+                       if(changed&MODERN_MATRIX)
+                       {
+                               const Matrix &m = mtx_stack.top();
+                               standard_shdata.uniform("eye_obj_matrix", mtx_stack.top());
+                               LinAl::SquareMatrix<float, 3> nm;
+                               for(unsigned i=0; i<3; ++i)
+                                       for(unsigned j=0; j<3; ++j)
+                                               nm(i, j) = m(i, j);
+                               nm = transpose(invert(nm));
+                               standard_shdata.uniform_matrix3("eye_obj_normal_matrix", &nm(0, 0));
+                               changed &= ~MODERN_MATRIX;
+                       }
+
                        if(state->material)
                                state->material->get_shader_data().apply();
                        standard_shdata.apply();
                }
 
-               if(changed&SHADER_DATA)
+               if((changed&SHADER_DATA) || shprog_changed)
                {
-                       for(vector<const ProgramData *>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
+                       vector<const ProgramData *>::const_iterator i = shdata_stack.begin();
+                       if(!shprog_changed)
+                               i += shdata_applied;
+                       for(; i!=shdata_stack.end(); ++i)
                                (*i)->apply();
                        changed &= ~SHADER_DATA;
+                       shdata_applied = shdata_stack.size();
                }
        }
        else
@@ -305,10 +323,10 @@ void Renderer::apply_state()
                        matrices_loaded = true;
                }
 
-               if(changed&MATRIX)
+               if(changed&LEGACY_MATRIX)
                {
                        MatrixStack::modelview() = mtx_stack.top();
-                       changed &= ~MATRIX;
+                       changed &= ~LEGACY_MATRIX;
                }
        }
 }
index a3ddaa3bd28f3832ce2a21884384727c897ede5f..dd9464127d025ee0ae4ba9612084f91617f8ad67 100644 (file)
@@ -91,7 +91,9 @@ private:
 
        enum ChangeMask
        {
-               MATRIX = 1,
+               LEGACY_MATRIX = 1,
+               MODERN_MATRIX = 2,
+               MATRIX = LEGACY_MATRIX|MODERN_MATRIX,
                LIGHTING = 4,
                SHADER_DATA = 8
        };
@@ -99,6 +101,7 @@ private:
        MtxStack mtx_stack;
        unsigned char changed;
        bool matrices_loaded;
+       unsigned shdata_applied;
        const Camera *camera;
        std::vector<State> state_stack;
        State *state;