diff options
author | marha <marha@users.sourceforge.net> | 2012-05-15 15:07:22 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-05-15 15:07:22 +0200 |
commit | 9818207986d5db9831e43eb2a640be68f54bb2ef (patch) | |
tree | e1ac6d17b2da887a2110c1337f01fc6fbdfa68fd /mesalib/src/glsl | |
parent | e6ff1fe09702cb307729b3208175c84f623f2968 (diff) | |
parent | 062c45ff0df6a52080dcd74433710d47127cbe29 (diff) | |
download | vcxsrv-9818207986d5db9831e43eb2a640be68f54bb2ef.tar.gz vcxsrv-9818207986d5db9831e43eb2a640be68f54bb2ef.tar.bz2 vcxsrv-9818207986d5db9831e43eb2a640be68f54bb2ef.zip |
Merge remote-tracking branch 'origin/released'
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/Makefile.sources | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.cpp | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_optimization.h | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 11 | ||||
-rw-r--r-- | mesalib/src/glsl/lower_discard_flow.cpp | 144 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_discard_simplification.cpp | 205 | ||||
-rw-r--r-- | mesalib/src/glsl/test_optpass.cpp | 2 |
7 files changed, 157 insertions, 209 deletions
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 5621e42b2..fba03604c 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -51,6 +51,7 @@ LIBGLSL_CXX_FILES := \ loop_unroll.cpp \ lower_clip_distance.cpp \ lower_discard.cpp \ + lower_discard_flow.cpp \ lower_if_to_cond_assign.cpp \ lower_instructions.cpp \ lower_jumps.cpp \ @@ -72,7 +73,6 @@ LIBGLSL_CXX_FILES := \ opt_dead_code.cpp \ opt_dead_code_local.cpp \ opt_dead_functions.cpp \ - opt_discard_simplification.cpp \ opt_function_inlining.cpp \ opt_if_simplification.cpp \ opt_noop_swizzle.cpp \ diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 6f1c86b43..46f21dd07 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -1044,7 +1044,6 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_structure_splitting(ir) || progress; } progress = do_if_simplification(ir) || progress; - progress = do_discard_simplification(ir) || progress; progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; if (linked) diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 356783583..c435d7717 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -66,6 +66,7 @@ bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); bool do_vec_index_to_swizzle(exec_list *instructions); bool lower_discard(exec_list *instructions); +void lower_discard_flow(exec_list *instructions); bool lower_instructions(exec_list *instructions, unsigned what_to_lower); bool lower_noise(exec_list *instructions); bool lower_variable_index_to_cond_assign(exec_list *instructions, diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 6ba297237..bdab499f0 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -2296,6 +2296,17 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->LinkStatus = true; } + /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do + * it before optimization because we want most of the checks to get + * dropped thanks to constant propagation. + */ + if (max_version >= 130) { + struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; + if (sh) { + lower_discard_flow(sh->ir); + } + } + /* Do common optimization before assigning storage for attributes, * uniforms, and varyings. Later optimization could possibly make * some of that unused. diff --git a/mesalib/src/glsl/lower_discard_flow.cpp b/mesalib/src/glsl/lower_discard_flow.cpp new file mode 100644 index 000000000..d385c1435 --- /dev/null +++ b/mesalib/src/glsl/lower_discard_flow.cpp @@ -0,0 +1,144 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** @file lower_discard_flow.cpp + * + * Implements the GLSL 1.30 revision 9 rule for fragment shader + * discard handling: + * + * "Control flow exits the shader, and subsequent implicit or + * explicit derivatives are undefined when this control flow is + * non-uniform (meaning different fragments within the primitive + * take different control paths)." + * + * There seem to be two conflicting things here. "Control flow exits + * the shader" sounds like the discarded fragments should effectively + * jump to the end of the shader, but that breaks derivatives in the + * case of uniform control flow and causes rendering failure in the + * bushes in Unigine Tropics. + * + * The question, then, is whether the intent was "loops stop at the + * point that the only active channels left are discarded pixels" or + * "discarded pixels become inactive at the point that control flow + * returns to the top of a loop". This implements the second + * interpretation. + */ + +#include "glsl_types.h" +#include "ir.h" +#include "program/hash_table.h" + +class lower_discard_flow_visitor : public ir_hierarchical_visitor { +public: + lower_discard_flow_visitor(ir_variable *discarded) + : discarded(discarded) + { + mem_ctx = ralloc_parent(discarded); + } + + ~lower_discard_flow_visitor() + { + } + + ir_visitor_status visit_enter(ir_discard *ir); + ir_visitor_status visit_enter(ir_loop_jump *ir); + ir_visitor_status visit_enter(ir_loop *ir); + ir_visitor_status visit_enter(ir_function_signature *ir); + + ir_if *generate_discard_break(); + + ir_variable *discarded; + void *mem_ctx; +}; + +ir_visitor_status +lower_discard_flow_visitor::visit_enter(ir_loop_jump *ir) +{ + if (ir->mode != ir_loop_jump::jump_continue) + return visit_continue; + + ir->insert_before(generate_discard_break()); + + return visit_continue; +} + +ir_visitor_status +lower_discard_flow_visitor::visit_enter(ir_discard *ir) +{ + ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded); + ir_rvalue *rhs = new(mem_ctx) ir_constant(true); + ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs); + ir->insert_before(assign); + + return visit_continue; +} + +ir_visitor_status +lower_discard_flow_visitor::visit_enter(ir_loop *ir) +{ + ir->body_instructions.push_tail(generate_discard_break()); + + return visit_continue; +} + +ir_visitor_status +lower_discard_flow_visitor::visit_enter(ir_function_signature *ir) +{ + if (strcmp(ir->function_name(), "main") != 0) + return visit_continue; + + ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded); + ir_rvalue *rhs = new(mem_ctx) ir_constant(false); + ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs); + ir->body.push_head(assign); + + return visit_continue; +} + +ir_if * +lower_discard_flow_visitor::generate_discard_break() +{ + ir_rvalue *if_condition = new(mem_ctx) ir_dereference_variable(discarded); + ir_if *if_inst = new(mem_ctx) ir_if(if_condition); + + ir_instruction *br = new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); + if_inst->then_instructions.push_tail(br); + + return if_inst; +} + +void +lower_discard_flow(exec_list *ir) +{ + void *mem_ctx = ir; + + ir_variable *var = new(mem_ctx) ir_variable(glsl_type::bool_type, + "discarded", + ir_var_temporary); + + ir->push_head(var); + + lower_discard_flow_visitor v(var); + + visit_list_elements(&v, ir); +} diff --git a/mesalib/src/glsl/opt_discard_simplification.cpp b/mesalib/src/glsl/opt_discard_simplification.cpp deleted file mode 100644 index ba4981bae..000000000 --- a/mesalib/src/glsl/opt_discard_simplification.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/** - * \file opt_discard_simplification.cpp - * - * This pass simplifies if-statements and loops containing unconditional - * discards. - * - * Case 1: Both branches contain unconditional discards: - * ----------------------------------------------------- - * - * if (cond) { - * s1; - * discard; - * s2; - * } else { - * s3; - * discard; - * s4; - * } - * - * becomes: - * - * discard - * - * Case 2: The "then" clause contains an unconditional discard: - * ------------------------------------------------------------ - * - * if (cond) { - * s1; - * discard; - * s2; - * } else { - * s3; - * } - * - * becomes: - * - * if (cond) { - * discard; - * } else { - * s3; - * } - * - * Case 3: The "else" clause contains an unconditional discard: - * ------------------------------------------------------------ - * - * if (cond) { - * s1; - * } else { - * s2; - * discard; - * s3; - * } - * - * becomes: - * - * if (cond) { - * s1; - * } else { - * discard; - * } - */ - -#include "glsl_types.h" -#include "ir.h" - -class discard_simplifier : public ir_hierarchical_visitor { -public: - discard_simplifier() - { - this->progress = false; - } - - ir_visitor_status visit_enter(ir_if *); - ir_visitor_status visit_enter(ir_loop *); - ir_visitor_status visit_enter(ir_assignment *); - - bool progress; -}; - -static ir_discard * -find_unconditional_discard(exec_list &instructions) -{ - foreach_list(n, &instructions) { - ir_instruction *ir = (ir_instruction *)n; - - if (ir->ir_type == ir_type_return || - ir->ir_type == ir_type_loop_jump) - return NULL; - - /* So far, this code doesn't know how to look inside of flow - * control to see if a discard later on at this level is - * unconditional. - */ - if (ir->ir_type == ir_type_if || - ir->ir_type == ir_type_loop) - return NULL; - - ir_discard *discard = ir->as_discard(); - if (discard != NULL && discard->condition == NULL) - return discard; - } - return NULL; -} - -static bool -is_only_instruction(ir_discard *discard) -{ - return (discard->prev->is_head_sentinel() && - discard->next->is_tail_sentinel()); -} - -/* We only care about the top level instructions, so don't descend - * into expressions. - */ -ir_visitor_status -discard_simplifier::visit_enter(ir_assignment *ir) -{ - (void) ir; - return visit_continue_with_parent; -} - -ir_visitor_status -discard_simplifier::visit_enter(ir_if *ir) -{ - ir_discard *then_discard = find_unconditional_discard(ir->then_instructions); - ir_discard *else_discard = find_unconditional_discard(ir->else_instructions); - - if (then_discard == NULL && else_discard == NULL) - return visit_continue; - - /* If both branches result in discard, replace whole if with discard. */ - if (then_discard != NULL && else_discard != NULL) { - this->progress = true; - ir->replace_with(then_discard); - return visit_continue_with_parent; - } - - /* Otherwise, one branch has a discard. */ - if (then_discard != NULL && !is_only_instruction(then_discard)) { - this->progress = true; - ir->then_instructions.make_empty(); - ir->then_instructions.push_tail(then_discard); - } else if (else_discard != NULL && !is_only_instruction(else_discard)) { - this->progress = true; - ir->else_instructions.make_empty(); - ir->else_instructions.push_tail(else_discard); - } - - visit_list_elements(this, &ir->then_instructions); - return visit_continue_with_parent; -} - -ir_visitor_status -discard_simplifier::visit_enter(ir_loop *ir) -{ - ir_discard *discard = find_unconditional_discard(ir->body_instructions); - - if (discard) { - ir->replace_with(discard); - return visit_continue_with_parent; - } - - return visit_continue; -} - -bool -do_discard_simplification(exec_list *instructions) -{ - /* Look for a top-level unconditional discard */ - ir_discard *discard = find_unconditional_discard(*instructions); - if (discard != NULL) { - instructions->make_empty(); - instructions->push_tail(discard); - return true; - } - - discard_simplifier v; - - visit_list_elements(&v, instructions); - - return v.progress; -} diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp index 6abafb5d3..31f65c3d2 100644 --- a/mesalib/src/glsl/test_optpass.cpp +++ b/mesalib/src/glsl/test_optpass.cpp @@ -98,8 +98,6 @@ do_optimization(struct exec_list *ir, const char *optimization) return do_lower_texture_projection(ir); } else if (strcmp(optimization, "do_if_simplification") == 0) { return do_if_simplification(ir); - } else if (strcmp(optimization, "do_discard_simplification") == 0) { - return do_discard_simplification(ir); } else if (sscanf(optimization, "lower_if_to_cond_assign ( %d ) ", &int_0) == 1) { return lower_if_to_cond_assign(ir, int_0); |