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 ir_set_program_inouts.cpp
  26.  *
  27.  * Sets the InputsRead and OutputsWritten of Mesa programs.
  28.  *
  29.  * Additionally, for fragment shaders, sets the InterpQualifier array, the
  30.  * IsCentroid bitfield, and the UsesDFdy flag.
  31.  *
  32.  * Mesa programs (gl_program, not gl_shader_program) have a set of
  33.  * flags indicating which varyings are read and written.  Computing
  34.  * which are actually read from some sort of backend code can be
  35.  * tricky when variable array indexing involved.  So this pass
  36.  * provides support for setting InputsRead and OutputsWritten right
  37.  * from the GLSL IR.
  38.  */
  39.  
  40. #include "main/core.h" /* for struct gl_program */
  41. #include "ir.h"
  42. #include "ir_visitor.h"
  43. #include "glsl_types.h"
  44.  
  45. class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
  46. public:
  47.    ir_set_program_inouts_visitor(struct gl_program *prog,
  48.                                  bool is_fragment_shader)
  49.    {
  50.       this->prog = prog;
  51.       this->is_fragment_shader = is_fragment_shader;
  52.    }
  53.    ~ir_set_program_inouts_visitor()
  54.    {
  55.    }
  56.  
  57.    virtual ir_visitor_status visit_enter(ir_dereference_array *);
  58.    virtual ir_visitor_status visit_enter(ir_function_signature *);
  59.    virtual ir_visitor_status visit_enter(ir_expression *);
  60.    virtual ir_visitor_status visit_enter(ir_discard *);
  61.    virtual ir_visitor_status visit(ir_dereference_variable *);
  62.  
  63.    struct gl_program *prog;
  64.    bool is_fragment_shader;
  65. };
  66.  
  67. static inline bool
  68. is_shader_inout(ir_variable *var)
  69. {
  70.    return var->mode == ir_var_shader_in ||
  71.           var->mode == ir_var_shader_out ||
  72.           var->mode == ir_var_system_value;
  73. }
  74.  
  75. static void
  76. mark(struct gl_program *prog, ir_variable *var, int offset, int len,
  77.      bool is_fragment_shader)
  78. {
  79.    /* As of GLSL 1.20, varyings can only be floats, floating-point
  80.     * vectors or matrices, or arrays of them.  For Mesa programs using
  81.     * InputsRead/OutputsWritten, everything but matrices uses one
  82.     * slot, while matrices use a slot per column.  Presumably
  83.     * something doing a more clever packing would use something other
  84.     * than InputsRead/OutputsWritten.
  85.     */
  86.  
  87.    for (int i = 0; i < len; i++) {
  88.       GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i);
  89.       if (var->mode == ir_var_shader_in) {
  90.          prog->InputsRead |= bitfield;
  91.          if (is_fragment_shader) {
  92.             gl_fragment_program *fprog = (gl_fragment_program *) prog;
  93.             fprog->InterpQualifier[var->location + var->index + offset + i] =
  94.                (glsl_interp_qualifier) var->interpolation;
  95.             if (var->centroid)
  96.                fprog->IsCentroid |= bitfield;
  97.          }
  98.       } else if (var->mode == ir_var_system_value) {
  99.          prog->SystemValuesRead |= bitfield;
  100.       } else {
  101.          assert(var->mode == ir_var_shader_out);
  102.          prog->OutputsWritten |= bitfield;
  103.       }
  104.    }
  105. }
  106.  
  107. /* Default handler: Mark all the locations in the variable as used. */
  108. ir_visitor_status
  109. ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
  110. {
  111.    if (!is_shader_inout(ir->var))
  112.       return visit_continue;
  113.  
  114.    if (ir->type->is_array()) {
  115.       mark(this->prog, ir->var, 0,
  116.            ir->type->length * ir->type->fields.array->matrix_columns,
  117.            this->is_fragment_shader);
  118.    } else {
  119.       mark(this->prog, ir->var, 0, ir->type->matrix_columns,
  120.            this->is_fragment_shader);
  121.    }
  122.  
  123.    return visit_continue;
  124. }
  125.  
  126. ir_visitor_status
  127. ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
  128. {
  129.    ir_dereference_variable *deref_var;
  130.    ir_constant *index = ir->array_index->as_constant();
  131.    deref_var = ir->array->as_dereference_variable();
  132.    ir_variable *var = deref_var ? deref_var->var : NULL;
  133.  
  134.    /* Check that we're dereferencing a shader in or out */
  135.    if (!var || !is_shader_inout(var))
  136.       return visit_continue;
  137.  
  138.    if (index) {
  139.       int width = 1;
  140.  
  141.       if (deref_var->type->is_array() &&
  142.           deref_var->type->fields.array->is_matrix()) {
  143.          width = deref_var->type->fields.array->matrix_columns;
  144.       }
  145.  
  146.       mark(this->prog, var, index->value.i[0] * width, width,
  147.            this->is_fragment_shader);
  148.       return visit_continue_with_parent;
  149.    }
  150.  
  151.    return visit_continue;
  152. }
  153.  
  154. ir_visitor_status
  155. ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
  156. {
  157.    /* We don't want to descend into the function parameters and
  158.     * consider them as shader inputs or outputs.
  159.     */
  160.    visit_list_elements(this, &ir->body);
  161.    return visit_continue_with_parent;
  162. }
  163.  
  164. ir_visitor_status
  165. ir_set_program_inouts_visitor::visit_enter(ir_expression *ir)
  166. {
  167.    if (is_fragment_shader && ir->operation == ir_unop_dFdy) {
  168.       gl_fragment_program *fprog = (gl_fragment_program *) prog;
  169.       fprog->UsesDFdy = true;
  170.    }
  171.    return visit_continue;
  172. }
  173.  
  174. ir_visitor_status
  175. ir_set_program_inouts_visitor::visit_enter(ir_discard *)
  176. {
  177.    /* discards are only allowed in fragment shaders. */
  178.    assert(is_fragment_shader);
  179.  
  180.    gl_fragment_program *fprog = (gl_fragment_program *) prog;
  181.    fprog->UsesKill = true;
  182.  
  183.    return visit_continue;
  184. }
  185.  
  186. void
  187. do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
  188.                       bool is_fragment_shader)
  189. {
  190.    ir_set_program_inouts_visitor v(prog, is_fragment_shader);
  191.  
  192.    prog->InputsRead = 0;
  193.    prog->OutputsWritten = 0;
  194.    prog->SystemValuesRead = 0;
  195.    if (is_fragment_shader) {
  196.       gl_fragment_program *fprog = (gl_fragment_program *) prog;
  197.       memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier));
  198.       fprog->IsCentroid = 0;
  199.       fprog->UsesDFdy = false;
  200.       fprog->UsesKill = false;
  201.    }
  202.    visit_list_elements(&v, instructions);
  203. }
  204.