X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.cpp;h=95bf1c0b1a0f4e58fc9b717ebeb22d0ecda455b6;hp=a4d9c86761a48458a35a340ee5884c3156ac670a;hb=f5e3256da7d8e3a56c002da47bedf8ec1a2133f4;hpb=8ee9712bae3cff206b3e3205748633edb33cbbcf diff --git a/effect_chain.cpp b/effect_chain.cpp index a4d9c86..95bf1c0 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -163,7 +163,7 @@ Node *EffectChain::add_node(Effect *effect) node->output_color_space = COLORSPACE_INVALID; node->output_gamma_curve = GAMMA_INVALID; node->output_alpha_type = ALPHA_INVALID; - node->needs_mipmaps = false; + node->needs_mipmaps = Effect::DOES_NOT_NEED_MIPMAPS; node->one_to_one_sampling = false; node->strong_one_to_one_sampling = false; @@ -523,6 +523,7 @@ void EffectChain::compile_glsl_program(Phase *phase) if (phase->is_compute_shader) { frag_shader.append(read_file("footer.comp")); + phase->compute_shader_node->effect->register_uniform_ivec2("output_size", phase->uniform_output_size); phase->compute_shader_node->effect->register_uniform_vec2("inv_output_size", (float *)&phase->inv_output_size); phase->compute_shader_node->effect->register_uniform_vec2("output_texcoord_adjust", (float *)&phase->output_texcoord_adjust); } else { @@ -544,6 +545,7 @@ void EffectChain::compile_glsl_program(Phase *phase) extract_uniform_declarations(effect->uniforms_sampler2d, "sampler2D", effect_id, &phase->uniforms_sampler2d, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_bool, "bool", effect_id, &phase->uniforms_bool, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_int, "int", effect_id, &phase->uniforms_int, &frag_shader_uniforms); + extract_uniform_declarations(effect->uniforms_ivec2, "ivec2", effect_id, &phase->uniforms_ivec2, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_float, "float", effect_id, &phase->uniforms_float, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_vec2, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_vec3, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms); @@ -555,20 +557,31 @@ void EffectChain::compile_glsl_program(Phase *phase) extract_uniform_declarations(effect->uniforms_mat3, "mat3", effect_id, &phase->uniforms_mat3, &frag_shader_uniforms); } - frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader; - string vert_shader = read_version_dependent_file("vs", "vert"); // If we're the last phase and need to flip the picture to compensate for - // the origin, tell the vertex shader so. - if (phase->output_node->outgoing_links.empty() && output_origin == OUTPUT_ORIGIN_TOP_LEFT) { - const string needle = "#define FLIP_ORIGIN 0"; - size_t pos = vert_shader.find(needle); - assert(pos != string::npos); + // the origin, tell the vertex or compute shader so. + bool is_last_phase; + if (has_dummy_effect) { + is_last_phase = (phase->output_node->outgoing_links.size() == 1 && + phase->output_node->outgoing_links[0]->effect->effect_type_id() == "ComputeShaderOutputDisplayEffect"); + } else { + is_last_phase = phase->output_node->outgoing_links.empty(); + } + if (is_last_phase && output_origin == OUTPUT_ORIGIN_TOP_LEFT) { + if (phase->is_compute_shader) { + frag_shader_header += "#define FLIP_ORIGIN 1\n"; + } else { + const string needle = "#define FLIP_ORIGIN 0"; + size_t pos = vert_shader.find(needle); + assert(pos != string::npos); - vert_shader[pos + needle.size() - 1] = '1'; + vert_shader[pos + needle.size() - 1] = '1'; + } } + frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader; + if (phase->is_compute_shader) { phase->glsl_program_num = resource_pool->compile_glsl_compute_program(frag_shader); @@ -596,6 +609,7 @@ void EffectChain::compile_glsl_program(Phase *phase) collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d); collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_bool); collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_int); + collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_ivec2); collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_float); collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec2); collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec3); @@ -641,8 +655,12 @@ Phase *EffectChain::construct_phase(Node *output, map *complete assert(node->effect->one_to_one_sampling() >= node->effect->strong_one_to_one_sampling()); - if (node->effect->needs_mipmaps()) { - node->needs_mipmaps = true; + if (node->effect->needs_mipmaps() != Effect::DOES_NOT_NEED_MIPMAPS) { + // Can't have incompatible requirements imposed on us from a dependent effect; + // if so, it should have started a new phase instead. + assert(node->needs_mipmaps == Effect::DOES_NOT_NEED_MIPMAPS || + node->needs_mipmaps == node->effect->needs_mipmaps()); + node->needs_mipmaps = node->effect->needs_mipmaps(); } // This should currently only happen for effects that are inputs @@ -680,12 +698,14 @@ Phase *EffectChain::construct_phase(Node *output, map *complete // Note that we cannot do this propagation as a normal pass, // because it needs information about where the phases end // (we should not propagate the flag across phases). - if (node->needs_mipmaps) { - if (deps[i]->effect->num_inputs() == 0) { + if (node->needs_mipmaps != Effect::DOES_NOT_NEED_MIPMAPS) { + if (deps[i]->effect->num_inputs() == 0 && node->needs_mipmaps == Effect::NEEDS_MIPMAPS) { Input *input = static_cast(deps[i]->effect); start_new_phase |= !input->can_supply_mipmaps(); - } else { - deps[i]->needs_mipmaps = true; + } else if (deps[i]->effect->needs_mipmaps() == Effect::DOES_NOT_NEED_MIPMAPS) { + deps[i]->needs_mipmaps = node->needs_mipmaps; + } else if (deps[i]->effect->needs_mipmaps() != node->needs_mipmaps) { + start_new_phase = true; } } @@ -774,7 +794,9 @@ Phase *EffectChain::construct_phase(Node *output, map *complete phase->input_needs_mipmaps = false; for (unsigned i = 0; i < phase->effects.size(); ++i) { Node *node = phase->effects[i]; - phase->input_needs_mipmaps |= node->effect->needs_mipmaps(); + if (node->effect->needs_mipmaps() == Effect::NEEDS_MIPMAPS) { + phase->input_needs_mipmaps = true; + } } for (unsigned i = 0; i < phase->effects.size(); ++i) { Node *node = phase->effects[i]; @@ -1039,7 +1061,7 @@ void EffectChain::inform_input_sizes(Phase *phase) // desired output size might change based on the inputs. void EffectChain::find_output_size(Phase *phase) { - Node *output_node = phase->effects.back(); + Node *output_node = phase->is_compute_shader ? phase->compute_shader_node : phase->effects.back(); // If the last effect explicitly sets an output size, use that. if (output_node->effect->changes_output_size()) { @@ -2143,6 +2165,8 @@ void EffectChain::execute_phase(Phase *phase, phase->outbuf_image_unit = 0; glBindImageTexture(phase->outbuf_image_unit, destinations[0].texnum, 0, GL_FALSE, 0, GL_WRITE_ONLY, destinations[0].format); check_error(); + phase->uniform_output_size[0] = phase->output_width; + phase->uniform_output_size[1] = phase->output_height; phase->inv_output_size.x = 1.0f / phase->output_width; phase->inv_output_size.y = 1.0f / phase->output_height; phase->output_texcoord_adjust.x = 0.5f / phase->output_width; @@ -2236,6 +2260,12 @@ void EffectChain::setup_uniforms(Phase *phase) glUniform1iv(uniform.location, uniform.num_values, uniform.value); } } + for (size_t i = 0; i < phase->uniforms_ivec2.size(); ++i) { + const Uniform &uniform = phase->uniforms_ivec2[i]; + if (uniform.location != -1) { + glUniform2iv(uniform.location, uniform.num_values, uniform.value); + } + } for (size_t i = 0; i < phase->uniforms_float.size(); ++i) { const Uniform &uniform = phase->uniforms_float[i]; if (uniform.location != -1) {