13de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt/*
23de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * Copyright © 2010 Intel Corporation
33de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
43de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
53de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * copy of this software and associated documentation files (the "Software"),
63de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * to deal in the Software without restriction, including without limitation
73de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * and/or sell copies of the Software, and to permit persons to whom the
93de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * Software is furnished to do so, subject to the following conditions:
103de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
113de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * The above copyright notice and this permission notice (including the next
123de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * paragraph) shall be included in all copies or substantial portions of the
133de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * Software.
143de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
153de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
183de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
193de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
203de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
213de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * DEALINGS IN THE SOFTWARE.
223de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt */
233de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
243de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt/** @file lower_discard_flow.cpp
253de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
263de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * Implements the GLSL 1.30 revision 9 rule for fragment shader
273de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * discard handling:
283de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
293de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *     "Control flow exits the shader, and subsequent implicit or
303de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *      explicit derivatives are undefined when this control flow is
313de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *      non-uniform (meaning different fragments within the primitive
323de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *      take different control paths)."
333de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
343de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * There seem to be two conflicting things here.  "Control flow exits
353de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * the shader" sounds like the discarded fragments should effectively
363de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * jump to the end of the shader, but that breaks derivatives in the
373de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * case of uniform control flow and causes rendering failure in the
383de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * bushes in Unigine Tropics.
393de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt *
403de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * The question, then, is whether the intent was "loops stop at the
413de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * point that the only active channels left are discarded pixels" or
423de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * "discarded pixels become inactive at the point that control flow
433de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * returns to the top of a loop".  This implements the second
443de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt * interpretation.
453de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt */
463de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
473de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt#include "glsl_types.h"
483de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt#include "ir.h"
493de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt#include "program/hash_table.h"
503de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
513de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtclass lower_discard_flow_visitor : public ir_hierarchical_visitor {
523de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtpublic:
533de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   lower_discard_flow_visitor(ir_variable *discarded)
543de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   : discarded(discarded)
553de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   {
563de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt      mem_ctx = ralloc_parent(discarded);
573de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   }
583de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
593de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ~lower_discard_flow_visitor()
603de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   {
613de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   }
623de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
633de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_visitor_status visit_enter(ir_discard *ir);
643de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_visitor_status visit_enter(ir_loop_jump *ir);
653de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_visitor_status visit_enter(ir_loop *ir);
663de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_visitor_status visit_enter(ir_function_signature *ir);
673de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
683de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_if *generate_discard_break();
693de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
703de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_variable *discarded;
713de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   void *mem_ctx;
723de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt};
733de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
743de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtir_visitor_status
753de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow_visitor::visit_enter(ir_loop_jump *ir)
763de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
773de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   if (ir->mode != ir_loop_jump::jump_continue)
783de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt      return visit_continue;
793de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
803de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir->insert_before(generate_discard_break());
813de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
823de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   return visit_continue;
833de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
843de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
853de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtir_visitor_status
863de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow_visitor::visit_enter(ir_discard *ir)
873de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
883de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded);
893de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_rvalue *rhs = new(mem_ctx) ir_constant(true);
903de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs);
913de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir->insert_before(assign);
923de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
933de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   return visit_continue;
943de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
953de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
963de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtir_visitor_status
973de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow_visitor::visit_enter(ir_loop *ir)
983de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
993de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir->body_instructions.push_tail(generate_discard_break());
1003de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1013de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   return visit_continue;
1023de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
1033de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1043de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtir_visitor_status
1053de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow_visitor::visit_enter(ir_function_signature *ir)
1063de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
1073de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   if (strcmp(ir->function_name(), "main") != 0)
1083de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt      return visit_continue;
1093de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1103de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded);
1113de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_rvalue *rhs = new(mem_ctx) ir_constant(false);
1123de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs);
1133de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir->body.push_head(assign);
1143de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1153de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   return visit_continue;
1163de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
1173de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1183de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtir_if *
1193de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow_visitor::generate_discard_break()
1203de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
1213de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_rvalue *if_condition = new(mem_ctx) ir_dereference_variable(discarded);
1223de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_if *if_inst = new(mem_ctx) ir_if(if_condition);
1233de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1243de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_instruction *br = new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break);
1253de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   if_inst->then_instructions.push_tail(br);
1263de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1273de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   return if_inst;
1283de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
1293de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1303de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtvoid
1313de1395fa5a563c13774ac1c38722c16cecc521dEric Anholtlower_discard_flow(exec_list *ir)
1323de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt{
1333de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   void *mem_ctx = ir;
1343de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1353de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir_variable *var = new(mem_ctx) ir_variable(glsl_type::bool_type,
1363de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt					       "discarded",
1373de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt					       ir_var_temporary);
1383de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1393de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   ir->push_head(var);
1403de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1413de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   lower_discard_flow_visitor v(var);
1423de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt
1433de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt   visit_list_elements(&v, ir);
1443de1395fa5a563c13774ac1c38722c16cecc521dEric Anholt}
145