+ // Which effects have already been completed in this phase?
+ // We need to keep track of it, as an effect with multiple outputs
+ // could otherwise be calculate multiple times.
+ std::set<Effect *> completed_effects;
+
+ // Effects in the current phase, as well as inputs (outputs from other phases
+ // that we depend on). Note that since we start iterating from the end,
+ // the effect list will be in the reverse order.
+ std::vector<Effect *> this_phase_inputs;
+ std::vector<Effect *> this_phase_effects;
+
+ // Effects that we have yet to calculate, but that we know should
+ // be in the current phase.
+ std::stack<Effect *> effects_todo_this_phase;
+
+ // Effects that we have yet to calculate, but that come from other phases.
+ // We delay these until we have this phase done in its entirety,
+ // at which point we pick any of them and start a new phase from that.
+ std::stack<Effect *> effects_todo_other_phases;
+
+ effects_todo_this_phase.push(output);
+
+ for ( ;; ) { // Termination condition within loop.
+ if (!effects_todo_this_phase.empty()) {
+ // OK, we have more to do this phase.
+ Effect *effect = effects_todo_this_phase.top();
+ effects_todo_this_phase.pop();
+
+ // This should currently only happen for effects that are phase outputs,
+ // and we throw those out separately below.
+ assert(completed_effects.count(effect) == 0);
+
+ this_phase_effects.push_back(effect);
+ completed_effects.insert(effect);
+
+ // Find all the dependencies of this effect, and add them to the stack.
+ assert(incoming_links.count(effect) == 1);
+ std::vector<Effect *> deps = incoming_links[effect];
+ assert(effect->num_inputs() == deps.size());
+ for (unsigned i = 0; i < deps.size(); ++i) {
+ bool start_new_phase = false;
+
+ if (effect->needs_texture_bounce()) {
+ start_new_phase = true;
+ }