Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2010 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. /**
  25.  * \file lower_vec_index_to_cond_assign.cpp
  26.  *
  27.  * Turns indexing into vector types to a series of conditional moves
  28.  * of each channel's swizzle into a temporary.
  29.  *
  30.  * Most GPUs don't have a native way to do this operation, and this
  31.  * works around that.  For drivers using both this pass and
  32.  * ir_vec_index_to_swizzle, there's a risk that this pass will happen
  33.  * before sufficient constant folding to find that the array index is
  34.  * constant.  However, we hope that other optimization passes,
  35.  * particularly constant folding of assignment conditions and copy
  36.  * propagation, will result in the same code in the end.
  37.  */
  38.  
  39. #include "ir.h"
  40. #include "ir_visitor.h"
  41. #include "ir_optimization.h"
  42. #include "glsl_types.h"
  43.  
  44. /**
  45.  * Visitor class for replacing expressions with ir_constant values.
  46.  */
  47.  
  48. class ir_vec_index_to_cond_assign_visitor : public ir_hierarchical_visitor {
  49. public:
  50.    ir_vec_index_to_cond_assign_visitor()
  51.    {
  52.       progress = false;
  53.    }
  54.  
  55.    ir_rvalue *convert_vec_index_to_cond_assign(void *mem_ctx,
  56.                                                ir_rvalue *orig_vector,
  57.                                                ir_rvalue *orig_index,
  58.                                                const glsl_type *type);
  59.  
  60.    ir_rvalue *convert_vector_extract_to_cond_assign(ir_rvalue *ir);
  61.  
  62.    virtual ir_visitor_status visit_enter(ir_expression *);
  63.    virtual ir_visitor_status visit_enter(ir_swizzle *);
  64.    virtual ir_visitor_status visit_leave(ir_assignment *);
  65.    virtual ir_visitor_status visit_enter(ir_return *);
  66.    virtual ir_visitor_status visit_enter(ir_call *);
  67.    virtual ir_visitor_status visit_enter(ir_if *);
  68.  
  69.    bool progress;
  70. };
  71.  
  72. ir_rvalue *
  73. ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(void *mem_ctx,
  74.                                                                       ir_rvalue *orig_vector,
  75.                                                                       ir_rvalue *orig_index,
  76.                                                                       const glsl_type *type)
  77. {
  78.    ir_assignment *assign, *value_assign;
  79.    ir_variable *index, *var, *value;
  80.    ir_dereference *deref, *deref_value;
  81.    unsigned i;
  82.  
  83.  
  84.    exec_list list;
  85.  
  86.    /* Store the index to a temporary to avoid reusing its tree. */
  87.    index = new(base_ir) ir_variable(glsl_type::int_type,
  88.                                     "vec_index_tmp_i",
  89.                                     ir_var_temporary);
  90.    list.push_tail(index);
  91.    deref = new(base_ir) ir_dereference_variable(index);
  92.    assign = new(base_ir) ir_assignment(deref, orig_index, NULL);
  93.    list.push_tail(assign);
  94.  
  95.    /* Store the value inside a temp, thus avoiding matrixes duplication */
  96.    value = new(base_ir) ir_variable(orig_vector->type, "vec_value_tmp",
  97.                                     ir_var_temporary);
  98.    list.push_tail(value);
  99.    deref_value = new(base_ir) ir_dereference_variable(value);
  100.    value_assign = new(base_ir) ir_assignment(deref_value, orig_vector);
  101.    list.push_tail(value_assign);
  102.  
  103.    /* Temporary where we store whichever value we swizzle out. */
  104.    var = new(base_ir) ir_variable(type, "vec_index_tmp_v",
  105.                                   ir_var_temporary);
  106.    list.push_tail(var);
  107.  
  108.    /* Generate a single comparison condition "mask" for all of the components
  109.     * in the vector.
  110.     */
  111.    ir_rvalue *const cond_deref =
  112.       compare_index_block(&list, index, 0,
  113.                           orig_vector->type->vector_elements,
  114.                           mem_ctx);
  115.  
  116.    /* Generate a conditional move of each vector element to the temp. */
  117.    for (i = 0; i < orig_vector->type->vector_elements; i++) {
  118.       ir_rvalue *condition_swizzle =
  119.          new(base_ir) ir_swizzle(cond_deref->clone(mem_ctx, NULL),
  120.                                  i, 0, 0, 0, 1);
  121.  
  122.       /* Just clone the rest of the deref chain when trying to get at the
  123.        * underlying variable.
  124.        */
  125.       ir_rvalue *swizzle =
  126.          new(base_ir) ir_swizzle(deref_value->clone(mem_ctx, NULL),
  127.                                  i, 0, 0, 0, 1);
  128.  
  129.       deref = new(base_ir) ir_dereference_variable(var);
  130.       assign = new(base_ir) ir_assignment(deref, swizzle, condition_swizzle);
  131.       list.push_tail(assign);
  132.    }
  133.  
  134.    /* Put all of the new instructions in the IR stream before the old
  135.     * instruction.
  136.     */
  137.    base_ir->insert_before(&list);
  138.  
  139.    this->progress = true;
  140.    return new(base_ir) ir_dereference_variable(var);
  141. }
  142.  
  143. ir_rvalue *
  144. ir_vec_index_to_cond_assign_visitor::convert_vector_extract_to_cond_assign(ir_rvalue *ir)
  145. {
  146.    ir_expression *const expr = ir->as_expression();
  147.  
  148.    if (expr == NULL || expr->operation != ir_binop_vector_extract)
  149.       return ir;
  150.  
  151.    return convert_vec_index_to_cond_assign(ralloc_parent(ir),
  152.                                            expr->operands[0],
  153.                                            expr->operands[1],
  154.                                            ir->type);
  155. }
  156.  
  157. ir_visitor_status
  158. ir_vec_index_to_cond_assign_visitor::visit_enter(ir_expression *ir)
  159. {
  160.    unsigned int i;
  161.  
  162.    for (i = 0; i < ir->get_num_operands(); i++) {
  163.       ir->operands[i] = convert_vector_extract_to_cond_assign(ir->operands[i]);
  164.    }
  165.  
  166.    return visit_continue;
  167. }
  168.  
  169. ir_visitor_status
  170. ir_vec_index_to_cond_assign_visitor::visit_enter(ir_swizzle *ir)
  171. {
  172.    /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
  173.     * the result of indexing a vector is.  But maybe at some point we'll end up
  174.     * using swizzling of scalars for vector construction.
  175.     */
  176.    ir->val = convert_vector_extract_to_cond_assign(ir->val);
  177.  
  178.    return visit_continue;
  179. }
  180.  
  181. ir_visitor_status
  182. ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
  183. {
  184.    ir->rhs = convert_vector_extract_to_cond_assign(ir->rhs);
  185.  
  186.    if (ir->condition) {
  187.       ir->condition = convert_vector_extract_to_cond_assign(ir->condition);
  188.    }
  189.  
  190.    return visit_continue;
  191. }
  192.  
  193. ir_visitor_status
  194. ir_vec_index_to_cond_assign_visitor::visit_enter(ir_call *ir)
  195. {
  196.    foreach_iter(exec_list_iterator, iter, *ir) {
  197.       ir_rvalue *param = (ir_rvalue *)iter.get();
  198.       ir_rvalue *new_param = convert_vector_extract_to_cond_assign(param);
  199.  
  200.       if (new_param != param) {
  201.          param->replace_with(new_param);
  202.       }
  203.    }
  204.  
  205.    return visit_continue;
  206. }
  207.  
  208. ir_visitor_status
  209. ir_vec_index_to_cond_assign_visitor::visit_enter(ir_return *ir)
  210. {
  211.    if (ir->value) {
  212.       ir->value = convert_vector_extract_to_cond_assign(ir->value);
  213.    }
  214.  
  215.    return visit_continue;
  216. }
  217.  
  218. ir_visitor_status
  219. ir_vec_index_to_cond_assign_visitor::visit_enter(ir_if *ir)
  220. {
  221.    ir->condition = convert_vector_extract_to_cond_assign(ir->condition);
  222.  
  223.    return visit_continue;
  224. }
  225.  
  226. bool
  227. do_vec_index_to_cond_assign(exec_list *instructions)
  228. {
  229.    ir_vec_index_to_cond_assign_visitor v;
  230.  
  231.    visit_list_elements(&v, instructions);
  232.  
  233.    return v.progress;
  234. }
  235.