Make VAOs persistent.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 18 Mar 2014 22:18:56 +0000 (23:18 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 18 Mar 2014 22:18:56 +0000 (23:18 +0100)
Seemingly helps ~0.5 ms/frame (which is quite significant for small
resolutions) on the demo applications on my NVidia card.

effect_chain.cpp
effect_chain.h

index 8d3c61d..487d7b7 100644 (file)
@@ -53,6 +53,15 @@ EffectChain::~EffectChain()
                delete nodes[i];
        }
        for (unsigned i = 0; i < phases.size(); ++i) {
+               glBindVertexArray(phases[i]->vao);
+               check_error();
+
+               cleanup_vertex_attribute(phases[i]->glsl_program_num, "position", phases[i]->position_vbo);
+               cleanup_vertex_attribute(phases[i]->glsl_program_num, "texcoord", phases[i]->texcoord_vbo);
+
+               glBindVertexArray(0);
+               check_error();
+
                resource_pool->release_glsl_program(phases[i]->glsl_program_num);
                delete phases[i];
        }
@@ -287,6 +296,27 @@ void EffectChain::compile_glsl_program(Phase *phase)
        frag_shader.append(read_file("footer.frag"));
 
        phase->glsl_program_num = resource_pool->compile_glsl_program(read_file("vs.vert"), frag_shader);
+
+       // Prepare the geometry for the fullscreen quad used in this phase.
+       // (We have separate VAOs per shader, since the bindings can in theory
+       // be different.)
+       float vertices[] = {
+               0.0f, 1.0f,
+               0.0f, 0.0f,
+               1.0f, 1.0f,
+               1.0f, 0.0f
+       };
+
+       glGenVertexArrays(1, &phase->vao);
+       check_error();
+       glBindVertexArray(phase->vao);
+       check_error();
+
+       phase->position_vbo = fill_vertex_attribute(phase->glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+       phase->texcoord_vbo = fill_vertex_attribute(phase->glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(vertices), vertices);  // Same as vertices.
+
+       glBindVertexArray(0);
+       check_error();
 }
 
 // Construct GLSL programs, starting at the given effect and following
@@ -1532,39 +1562,15 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                        }
                }
 
-               // Now draw!
-               float vertices[] = {
-                       0.0f, 1.0f,
-                       0.0f, 0.0f,
-                       1.0f, 1.0f,
-                       1.0f, 0.0f
-               };
-
-               GLuint vao;
-               glGenVertexArrays(1, &vao);
-               check_error();
-               glBindVertexArray(vao);
+               glBindVertexArray(phases[phase]->vao);
                check_error();
-
-               GLuint position_vbo = fill_vertex_attribute(glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
-               GLuint texcoord_vbo = fill_vertex_attribute(glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(vertices), vertices);  // Same as vertices.
-
                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                check_error();
 
-               cleanup_vertex_attribute(glsl_program_num, "position", position_vbo);
-               cleanup_vertex_attribute(glsl_program_num, "texcoord", texcoord_vbo);
-
-               glUseProgram(0);
-               check_error();
-
                for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
                        Node *node = phases[phase]->effects[i];
                        node->effect->clear_gl_state();
                }
-
-               glDeleteVertexArrays(1, &vao);
-               check_error();
        }
 
        for (map<Phase *, GLuint>::const_iterator texture_it = output_textures.begin();
@@ -1575,6 +1581,10 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
 
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        check_error();
+       glBindVertexArray(0);
+       check_error();
+       glUseProgram(0);
+       check_error();
 }
 
 }  // namespace movit
index 505e55a..9051195 100644 (file)
@@ -99,6 +99,13 @@ struct Phase {
        // Identifier used to create unique variables in GLSL.
        // Unique per-phase to increase cacheability of compiled shaders.
        std::map<Node *, std::string> effect_ids;
+
+       // The geometry needed to draw this quad, bound to the vertex array
+       // object. (Seemingly it's actually a win not to upload geometry every
+       // frame, even for something as small as a quad, due to fewer state
+       // changes.)
+       GLuint vao;
+       GLuint position_vbo, texcoord_vbo;
 };
 
 class EffectChain {