X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=effect_chain.cpp;h=d509fba391029866cb36c3288f2969c8c5b4baab;hb=abb7221a797bb5332f9ff9346396beb4c95dcc34;hp=a6ed91d5f20a51e406fafc0e79894e0b3f5f2cb0;hpb=dbaedda69333076ce33dce196075729fd11d9558;p=movit diff --git a/effect_chain.cpp b/effect_chain.cpp index a6ed91d..d509fba 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -330,13 +330,27 @@ void EffectChain::construct_glsl_programs(Node *output) start_new_phase = true; } - if (deps[i]->outgoing_links.size() > 1 && deps[i]->effect->num_inputs() > 0) { - // More than one effect uses this as the input, - // and it is not a texture itself. - // The easiest thing to do (and probably also the safest - // performance-wise in most cases) is to bounce it to a texture - // and then let the next passes read from that. - start_new_phase = true; + if (deps[i]->outgoing_links.size() > 1) { + if (deps[i]->effect->num_inputs() > 0) { + // More than one effect uses this as the input, + // and it is not a texture itself. + // The easiest thing to do (and probably also the safest + // performance-wise in most cases) is to bounce it to a texture + // and then let the next passes read from that. + start_new_phase = true; + } else { + // For textures, we try to be slightly more clever; + // if none of our outputs need a bounce, we don't bounce + // but instead simply use the effect many times. + // + // Strictly speaking, we could bounce it for some outputs + // and use it directly for others, but the processing becomes + // somewhat simpler if the effect is only used in one such way. + for (unsigned j = 0; j < deps[i]->outgoing_links.size(); ++j) { + Node *rdep = deps[i]->outgoing_links[j]; + start_new_phase |= rdep->effect->needs_texture_bounce(); + } + } } if (deps[i]->effect->changes_output_size()) { @@ -394,7 +408,23 @@ void EffectChain::output_dot(const char *filename) fprintf(fp, "digraph G {\n"); for (unsigned i = 0; i < nodes.size(); ++i) { - fprintf(fp, " n%ld [label=\"%s\"];\n", (long)nodes[i], nodes[i]->effect->effect_type_id().c_str()); + // Find out which phase this event belongs to. + int in_phase = -1; + for (unsigned j = 0; j < phases.size(); ++j) { + const Phase* p = phases[j]; + if (std::find(p->effects.begin(), p->effects.end(), nodes[i]) != p->effects.end()) { + assert(in_phase == -1); + in_phase = j; + } + } + + if (in_phase == -1) { + fprintf(fp, " n%ld [label=\"%s\"];\n", (long)nodes[i], nodes[i]->effect->effect_type_id().c_str()); + } else { + fprintf(fp, " n%ld [label=\"%s\" style=\"filled\" fillcolor=\"/accent8/%d\"];\n", + (long)nodes[i], nodes[i]->effect->effect_type_id().c_str(), + (in_phase % 8) + 1); + } for (unsigned j = 0; j < nodes[i]->outgoing_links.size(); ++j) { std::vector labels; @@ -934,6 +964,8 @@ void EffectChain::finalize() // Construct all needed GLSL programs, starting at the output. construct_glsl_programs(find_output_node()); + output_dot("step11-split-to-phases.dot"); + // If we have more than one phase, we need intermediate render-to-texture. // Construct an FBO, and then as many textures as we need. // We choose the simplest option of having one texture per output, @@ -973,7 +1005,7 @@ void EffectChain::finalize() finalized = true; } -void EffectChain::render_to_fbo(GLuint fbo, unsigned width, unsigned height) +void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height) { assert(finalized); @@ -1066,7 +1098,7 @@ void EffectChain::render_to_fbo(GLuint fbo, unsigned width, unsigned height) // And now the output. if (phase == phases.size() - 1) { // Last phase goes to the output the user specified. - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, dest_fbo); check_error(); glViewport(x, y, width, height); } else {