+ bind_sampler(densify_program, uniform_image_tex, 0, tex_view, linear_sampler);
+ bind_sampler(densify_program, uniform_flow_tex, 1, flow_tex, nearest_sampler);
+
+ glProgramUniform2f(densify_program, uniform_patch_size,
+ float(op.patch_size_pixels) / level_width,
+ float(op.patch_size_pixels) / level_height);
+
+ glViewport(0, 0, level_width, level_height);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ fbos.render_to(dense_flow_tex);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, width_patches * height_patches * num_layers);
+}
+
+Prewarp::Prewarp()
+{
+ prewarp_vs_obj = compile_shader(read_file("vs.vert", _binary_vs_vert_data, _binary_vs_vert_size), GL_VERTEX_SHADER);
+ prewarp_fs_obj = compile_shader(read_file("prewarp.frag", _binary_prewarp_frag_data, _binary_prewarp_frag_size), GL_FRAGMENT_SHADER);
+ prewarp_program = link_program(prewarp_vs_obj, prewarp_fs_obj);
+
+ uniform_image_tex = glGetUniformLocation(prewarp_program, "image_tex");
+ uniform_flow_tex = glGetUniformLocation(prewarp_program, "flow_tex");
+}
+
+void Prewarp::exec(GLuint tex_view, GLuint flow_tex, GLuint I_tex, GLuint I_t_tex, GLuint normalized_flow_tex, int level_width, int level_height, int num_layers)
+{
+ glUseProgram(prewarp_program);
+
+ bind_sampler(prewarp_program, uniform_image_tex, 0, tex_view, linear_sampler);
+ bind_sampler(prewarp_program, uniform_flow_tex, 1, flow_tex, nearest_sampler);
+
+ glViewport(0, 0, level_width, level_height);
+ glDisable(GL_BLEND);
+ fbos.render_to(I_tex, I_t_tex, normalized_flow_tex);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+}
+
+Derivatives::Derivatives()
+{
+ derivatives_vs_obj = compile_shader(read_file("vs.vert", _binary_vs_vert_data, _binary_vs_vert_size), GL_VERTEX_SHADER);
+ derivatives_fs_obj = compile_shader(read_file("derivatives.frag", _binary_derivatives_frag_data, _binary_derivatives_frag_size), GL_FRAGMENT_SHADER);
+ derivatives_program = link_program(derivatives_vs_obj, derivatives_fs_obj);
+
+ uniform_tex = glGetUniformLocation(derivatives_program, "tex");
+}
+
+void Derivatives::exec(GLuint input_tex, GLuint I_x_y_tex, GLuint beta_0_tex, int level_width, int level_height, int num_layers)
+{
+ glUseProgram(derivatives_program);
+
+ bind_sampler(derivatives_program, uniform_tex, 0, input_tex, nearest_sampler);
+
+ glViewport(0, 0, level_width, level_height);
+ glDisable(GL_BLEND);
+ fbos.render_to(I_x_y_tex, beta_0_tex);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+}
+
+ComputeDiffusivity::ComputeDiffusivity()
+{
+ diffusivity_vs_obj = compile_shader(read_file("vs.vert", _binary_vs_vert_data, _binary_vs_vert_size), GL_VERTEX_SHADER);
+ diffusivity_fs_obj = compile_shader(read_file("diffusivity.frag", _binary_diffusivity_frag_data, _binary_diffusivity_frag_size), GL_FRAGMENT_SHADER);
+ diffusivity_program = link_program(diffusivity_vs_obj, diffusivity_fs_obj);
+
+ uniform_flow_tex = glGetUniformLocation(diffusivity_program, "flow_tex");
+ uniform_diff_flow_tex = glGetUniformLocation(diffusivity_program, "diff_flow_tex");
+ uniform_alpha = glGetUniformLocation(diffusivity_program, "alpha");
+ uniform_zero_diff_flow = glGetUniformLocation(diffusivity_program, "zero_diff_flow");
+}
+
+void ComputeDiffusivity::exec(GLuint flow_tex, GLuint diff_flow_tex, GLuint diffusivity_tex, int level_width, int level_height, bool zero_diff_flow, int num_layers)
+{
+ glUseProgram(diffusivity_program);
+
+ bind_sampler(diffusivity_program, uniform_flow_tex, 0, flow_tex, nearest_sampler);
+ bind_sampler(diffusivity_program, uniform_diff_flow_tex, 1, diff_flow_tex, nearest_sampler);
+ glProgramUniform1f(diffusivity_program, uniform_alpha, vr_alpha);
+ glProgramUniform1i(diffusivity_program, uniform_zero_diff_flow, zero_diff_flow);
+
+ glViewport(0, 0, level_width, level_height);
+
+ glDisable(GL_BLEND);
+ fbos.render_to(diffusivity_tex);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+}
+
+SetupEquations::SetupEquations()
+{
+ equations_vs_obj = compile_shader(read_file("equations.vert", _binary_equations_vert_data, _binary_equations_vert_size), GL_VERTEX_SHADER);
+ equations_fs_obj = compile_shader(read_file("equations.frag", _binary_equations_frag_data, _binary_equations_frag_size), GL_FRAGMENT_SHADER);
+ equations_program = link_program(equations_vs_obj, equations_fs_obj);
+
+ uniform_I_x_y_tex = glGetUniformLocation(equations_program, "I_x_y_tex");
+ uniform_I_t_tex = glGetUniformLocation(equations_program, "I_t_tex");
+ uniform_diff_flow_tex = glGetUniformLocation(equations_program, "diff_flow_tex");
+ uniform_base_flow_tex = glGetUniformLocation(equations_program, "base_flow_tex");
+ uniform_beta_0_tex = glGetUniformLocation(equations_program, "beta_0_tex");
+ uniform_diffusivity_tex = glGetUniformLocation(equations_program, "diffusivity_tex");
+ uniform_gamma = glGetUniformLocation(equations_program, "gamma");
+ uniform_delta = glGetUniformLocation(equations_program, "delta");
+ uniform_zero_diff_flow = glGetUniformLocation(equations_program, "zero_diff_flow");
+}
+
+void SetupEquations::exec(GLuint I_x_y_tex, GLuint I_t_tex, GLuint diff_flow_tex, GLuint base_flow_tex, GLuint beta_0_tex, GLuint diffusivity_tex, GLuint equation_red_tex, GLuint equation_black_tex, int level_width, int level_height, bool zero_diff_flow, int num_layers)
+{
+ glUseProgram(equations_program);
+
+ bind_sampler(equations_program, uniform_I_x_y_tex, 0, I_x_y_tex, nearest_sampler);
+ bind_sampler(equations_program, uniform_I_t_tex, 1, I_t_tex, nearest_sampler);
+ bind_sampler(equations_program, uniform_diff_flow_tex, 2, diff_flow_tex, nearest_sampler);
+ bind_sampler(equations_program, uniform_base_flow_tex, 3, base_flow_tex, nearest_sampler);
+ bind_sampler(equations_program, uniform_beta_0_tex, 4, beta_0_tex, nearest_sampler);
+ bind_sampler(equations_program, uniform_diffusivity_tex, 5, diffusivity_tex, zero_border_sampler);
+ glProgramUniform1f(equations_program, uniform_delta, vr_delta);
+ glProgramUniform1f(equations_program, uniform_gamma, vr_gamma);
+ glProgramUniform1i(equations_program, uniform_zero_diff_flow, zero_diff_flow);
+
+ glViewport(0, 0, (level_width + 1) / 2, level_height);
+ glDisable(GL_BLEND);
+ fbos.render_to(equation_red_tex, equation_black_tex);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+}
+
+SOR::SOR()
+{
+ sor_vs_obj = compile_shader(read_file("sor.vert", _binary_sor_vert_data, _binary_sor_vert_size), GL_VERTEX_SHADER);
+ sor_fs_obj = compile_shader(read_file("sor.frag", _binary_sor_frag_data, _binary_sor_frag_size), GL_FRAGMENT_SHADER);
+ sor_program = link_program(sor_vs_obj, sor_fs_obj);
+
+ uniform_diff_flow_tex = glGetUniformLocation(sor_program, "diff_flow_tex");
+ uniform_equation_red_tex = glGetUniformLocation(sor_program, "equation_red_tex");
+ uniform_equation_black_tex = glGetUniformLocation(sor_program, "equation_black_tex");
+ uniform_diffusivity_tex = glGetUniformLocation(sor_program, "diffusivity_tex");
+ uniform_phase = glGetUniformLocation(sor_program, "phase");
+ uniform_num_nonzero_phases = glGetUniformLocation(sor_program, "num_nonzero_phases");
+}
+
+void SOR::exec(GLuint diff_flow_tex, GLuint equation_red_tex, GLuint equation_black_tex, GLuint diffusivity_tex, int level_width, int level_height, int num_iterations, bool zero_diff_flow, int num_layers, ScopedTimer *sor_timer)
+{
+ glUseProgram(sor_program);
+
+ bind_sampler(sor_program, uniform_diff_flow_tex, 0, diff_flow_tex, nearest_sampler);
+ bind_sampler(sor_program, uniform_diffusivity_tex, 1, diffusivity_tex, zero_border_sampler);
+ bind_sampler(sor_program, uniform_equation_red_tex, 2, equation_red_tex, nearest_sampler);
+ bind_sampler(sor_program, uniform_equation_black_tex, 3, equation_black_tex, nearest_sampler);
+
+ if (!zero_diff_flow) {
+ glProgramUniform1i(sor_program, uniform_num_nonzero_phases, 2);
+ }
+
+ // NOTE: We bind to the texture we are rendering from, but we never write any value
+ // that we read in the same shader pass (we call discard for red values when we compute
+ // black, and vice versa), and we have barriers between the passes, so we're fine
+ // as per the spec.
+ glViewport(0, 0, level_width, level_height);
+ glDisable(GL_BLEND);
+ fbos.render_to(diff_flow_tex);
+
+ for (int i = 0; i < num_iterations; ++i) {
+ {
+ ScopedTimer timer("Red pass", sor_timer);
+ if (zero_diff_flow && i == 0) {
+ glProgramUniform1i(sor_program, uniform_num_nonzero_phases, 0);
+ }
+ glProgramUniform1i(sor_program, uniform_phase, 0);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+ glTextureBarrier();
+ }
+ {
+ ScopedTimer timer("Black pass", sor_timer);
+ if (zero_diff_flow && i == 0) {
+ glProgramUniform1i(sor_program, uniform_num_nonzero_phases, 1);
+ }
+ glProgramUniform1i(sor_program, uniform_phase, 1);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_layers);
+ if (zero_diff_flow && i == 0) {
+ glProgramUniform1i(sor_program, uniform_num_nonzero_phases, 2);
+ }
+ if (i != num_iterations - 1) {
+ glTextureBarrier();
+ }
+ }
+ }
+}
+
+AddBaseFlow::AddBaseFlow()
+{
+ add_flow_vs_obj = compile_shader(read_file("vs.vert", _binary_vs_vert_data, _binary_vs_vert_size), GL_VERTEX_SHADER);
+ add_flow_fs_obj = compile_shader(read_file("add_base_flow.frag", _binary_add_base_flow_frag_data, _binary_add_base_flow_frag_size), GL_FRAGMENT_SHADER);
+ add_flow_program = link_program(add_flow_vs_obj, add_flow_fs_obj);