Home | History | Annotate | Download | only in glsl
      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 inputs_read and outputs_written of Mesa programs.
     28  *
     29  * Mesa programs (gl_program, not gl_shader_program) have a set of
     30  * flags indicating which varyings are read and written.  Computing
     31  * which are actually read from some sort of backend code can be
     32  * tricky when variable array indexing involved.  So this pass
     33  * provides support for setting inputs_read and outputs_written right
     34  * from the GLSL IR.
     35  */
     36 
     37 #include "main/core.h" /* for struct gl_program */
     38 #include "ir.h"
     39 #include "ir_visitor.h"
     40 #include "compiler/glsl_types.h"
     41 
     42 namespace {
     43 
     44 class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
     45 public:
     46    ir_set_program_inouts_visitor(struct gl_program *prog,
     47                                  gl_shader_stage shader_stage)
     48    {
     49       this->prog = prog;
     50       this->shader_stage = shader_stage;
     51    }
     52    ~ir_set_program_inouts_visitor()
     53    {
     54    }
     55 
     56    virtual ir_visitor_status visit_enter(ir_dereference_array *);
     57    virtual ir_visitor_status visit_enter(ir_function_signature *);
     58    virtual ir_visitor_status visit_enter(ir_discard *);
     59    virtual ir_visitor_status visit_enter(ir_texture *);
     60    virtual ir_visitor_status visit(ir_dereference_variable *);
     61 
     62 private:
     63    void mark_whole_variable(ir_variable *var);
     64    bool try_mark_partial_variable(ir_variable *var, ir_rvalue *index);
     65 
     66    struct gl_program *prog;
     67    gl_shader_stage shader_stage;
     68 };
     69 
     70 } /* anonymous namespace */
     71 
     72 static inline bool
     73 is_shader_inout(ir_variable *var)
     74 {
     75    return var->data.mode == ir_var_shader_in ||
     76           var->data.mode == ir_var_shader_out ||
     77           var->data.mode == ir_var_system_value;
     78 }
     79 
     80 static void
     81 mark(struct gl_program *prog, ir_variable *var, int offset, int len,
     82      gl_shader_stage stage)
     83 {
     84    /* As of GLSL 1.20, varyings can only be floats, floating-point
     85     * vectors or matrices, or arrays of them.  For Mesa programs using
     86     * inputs_read/outputs_written, everything but matrices uses one
     87     * slot, while matrices use a slot per column.  Presumably
     88     * something doing a more clever packing would use something other
     89     * than inputs_read/outputs_written.
     90     */
     91 
     92    for (int i = 0; i < len; i++) {
     93       assert(var->data.location != -1);
     94 
     95       int idx = var->data.location + offset + i;
     96       bool is_patch_generic = var->data.patch &&
     97                               idx != VARYING_SLOT_TESS_LEVEL_INNER &&
     98                               idx != VARYING_SLOT_TESS_LEVEL_OUTER &&
     99                               idx != VARYING_SLOT_BOUNDING_BOX0 &&
    100                               idx != VARYING_SLOT_BOUNDING_BOX1;
    101       GLbitfield64 bitfield;
    102 
    103       if (is_patch_generic) {
    104          assert(idx >= VARYING_SLOT_PATCH0 && idx < VARYING_SLOT_TESS_MAX);
    105          bitfield = BITFIELD64_BIT(idx - VARYING_SLOT_PATCH0);
    106       }
    107       else {
    108          assert(idx < VARYING_SLOT_MAX);
    109          bitfield = BITFIELD64_BIT(idx);
    110       }
    111 
    112       if (var->data.mode == ir_var_shader_in) {
    113          if (is_patch_generic)
    114             prog->info.patch_inputs_read |= bitfield;
    115          else
    116             prog->info.inputs_read |= bitfield;
    117 
    118          /* double inputs read is only for vertex inputs */
    119          if (stage == MESA_SHADER_VERTEX &&
    120              var->type->without_array()->is_dual_slot())
    121             prog->info.double_inputs_read |= bitfield;
    122 
    123          if (stage == MESA_SHADER_FRAGMENT) {
    124             prog->info.fs.uses_sample_qualifier |= var->data.sample;
    125          }
    126       } else if (var->data.mode == ir_var_system_value) {
    127          prog->info.system_values_read |= bitfield;
    128       } else {
    129          assert(var->data.mode == ir_var_shader_out);
    130          if (is_patch_generic) {
    131             prog->info.patch_outputs_written |= bitfield;
    132          } else if (!var->data.read_only) {
    133             prog->info.outputs_written |= bitfield;
    134             if (var->data.index > 0)
    135                prog->SecondaryOutputsWritten |= bitfield;
    136          }
    137 
    138          if (var->data.fb_fetch_output)
    139             prog->info.outputs_read |= bitfield;
    140       }
    141    }
    142 }
    143 
    144 /**
    145  * Mark an entire variable as used.  Caller must ensure that the variable
    146  * represents a shader input or output.
    147  */
    148 void
    149 ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var)
    150 {
    151    const glsl_type *type = var->type;
    152    bool is_vertex_input = false;
    153    if (this->shader_stage == MESA_SHADER_GEOMETRY &&
    154        var->data.mode == ir_var_shader_in && type->is_array()) {
    155       type = type->fields.array;
    156    }
    157 
    158    if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
    159        var->data.mode == ir_var_shader_in) {
    160       assert(type->is_array());
    161       type = type->fields.array;
    162    }
    163 
    164    if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
    165        var->data.mode == ir_var_shader_out && !var->data.patch) {
    166       assert(type->is_array());
    167       type = type->fields.array;
    168    }
    169 
    170    if (this->shader_stage == MESA_SHADER_TESS_EVAL &&
    171        var->data.mode == ir_var_shader_in && !var->data.patch) {
    172       assert(type->is_array());
    173       type = type->fields.array;
    174    }
    175 
    176    if (this->shader_stage == MESA_SHADER_VERTEX &&
    177        var->data.mode == ir_var_shader_in)
    178       is_vertex_input = true;
    179 
    180    mark(this->prog, var, 0, type->count_attribute_slots(is_vertex_input),
    181         this->shader_stage);
    182 }
    183 
    184 /* Default handler: Mark all the locations in the variable as used. */
    185 ir_visitor_status
    186 ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
    187 {
    188    if (!is_shader_inout(ir->var))
    189       return visit_continue;
    190 
    191    mark_whole_variable(ir->var);
    192 
    193    return visit_continue;
    194 }
    195 
    196 /**
    197  * Try to mark a portion of the given variable as used.  Caller must ensure
    198  * that the variable represents a shader input or output which can be indexed
    199  * into in array fashion (an array or matrix).  For the purpose of geometry
    200  * shader inputs (which are always arrays*), this means that the array element
    201  * must be something that can be indexed into in array fashion.
    202  *
    203  * *Except gl_PrimitiveIDIn, as noted below.
    204  *
    205  * For tessellation control shaders all inputs and non-patch outputs are
    206  * arrays. For tessellation evaluation shaders non-patch inputs are arrays.
    207  *
    208  * If the index can't be interpreted as a constant, or some other problem
    209  * occurs, then nothing will be marked and false will be returned.
    210  */
    211 bool
    212 ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
    213                                                          ir_rvalue *index)
    214 {
    215    const glsl_type *type = var->type;
    216 
    217    if (this->shader_stage == MESA_SHADER_GEOMETRY &&
    218        var->data.mode == ir_var_shader_in) {
    219       /* The only geometry shader input that is not an array is
    220        * gl_PrimitiveIDIn, and in that case, this code will never be reached,
    221        * because gl_PrimitiveIDIn can't be indexed into in array fashion.
    222        */
    223       assert(type->is_array());
    224       type = type->fields.array;
    225    }
    226 
    227    if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
    228        var->data.mode == ir_var_shader_in) {
    229       assert(type->is_array());
    230       type = type->fields.array;
    231    }
    232 
    233    if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
    234        var->data.mode == ir_var_shader_out && !var->data.patch) {
    235       assert(type->is_array());
    236       type = type->fields.array;
    237    }
    238 
    239    if (this->shader_stage == MESA_SHADER_TESS_EVAL &&
    240        var->data.mode == ir_var_shader_in && !var->data.patch) {
    241       assert(type->is_array());
    242       type = type->fields.array;
    243    }
    244 
    245    /* TODO: implement proper arrays of arrays support
    246     * for now let the caller mark whole variable as used.
    247     */
    248    if (type->is_array() && type->fields.array->is_array())
    249       return false;
    250 
    251    /* The code below only handles:
    252     *
    253     * - Indexing into matrices
    254     * - Indexing into arrays of (matrices, vectors, or scalars)
    255     *
    256     * All other possibilities are either prohibited by GLSL (vertex inputs and
    257     * fragment outputs can't be structs) or should have been eliminated by
    258     * lowering passes (do_vec_index_to_swizzle() gets rid of indexing into
    259     * vectors, and lower_packed_varyings() gets rid of structs that occur in
    260     * varyings).
    261     *
    262     * However, we don't use varying packing in all cases - tessellation
    263     * shaders bypass it.  This means we'll see varying structs and arrays
    264     * of structs here.  For now, we just give up so the caller marks the
    265     * entire variable as used.
    266     */
    267    if (!(type->is_matrix() ||
    268         (type->is_array() &&
    269          (type->fields.array->is_numeric() ||
    270           type->fields.array->is_boolean())))) {
    271 
    272       /* If we don't know how to handle this case, give up and let the
    273        * caller mark the whole variable as used.
    274        */
    275       return false;
    276    }
    277 
    278    ir_constant *index_as_constant = index->as_constant();
    279    if (!index_as_constant)
    280       return false;
    281 
    282    unsigned elem_width;
    283    unsigned num_elems;
    284    if (type->is_array()) {
    285       num_elems = type->length;
    286       if (type->fields.array->is_matrix())
    287          elem_width = type->fields.array->matrix_columns;
    288       else
    289          elem_width = 1;
    290    } else {
    291       num_elems = type->matrix_columns;
    292       elem_width = 1;
    293    }
    294 
    295    if (index_as_constant->value.u[0] >= num_elems) {
    296       /* Constant index outside the bounds of the matrix/array.  This could
    297        * arise as a result of constant folding of a legal GLSL program.
    298        *
    299        * Even though the spec says that indexing outside the bounds of a
    300        * matrix/array results in undefined behaviour, we don't want to pass
    301        * out-of-range values to mark() (since this could result in slots that
    302        * don't exist being marked as used), so just let the caller mark the
    303        * whole variable as used.
    304        */
    305       return false;
    306    }
    307 
    308    /* double element width for double types that takes two slots */
    309    if (this->shader_stage != MESA_SHADER_VERTEX ||
    310        var->data.mode != ir_var_shader_in) {
    311       if (type->without_array()->is_dual_slot())
    312 	 elem_width *= 2;
    313    }
    314 
    315    mark(this->prog, var, index_as_constant->value.u[0] * elem_width,
    316         elem_width, this->shader_stage);
    317    return true;
    318 }
    319 
    320 static bool
    321 is_multiple_vertices(gl_shader_stage stage, ir_variable *var)
    322 {
    323    if (var->data.patch)
    324       return false;
    325 
    326    if (var->data.mode == ir_var_shader_in)
    327       return stage == MESA_SHADER_GEOMETRY ||
    328              stage == MESA_SHADER_TESS_CTRL ||
    329              stage == MESA_SHADER_TESS_EVAL;
    330    if (var->data.mode == ir_var_shader_out)
    331       return stage == MESA_SHADER_TESS_CTRL;
    332 
    333    return false;
    334 }
    335 
    336 ir_visitor_status
    337 ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
    338 {
    339    /* Note: for geometry shader inputs, lower_named_interface_blocks may
    340     * create 2D arrays, so we need to be able to handle those.  2D arrays
    341     * shouldn't be able to crop up for any other reason.
    342     */
    343    if (ir_dereference_array * const inner_array =
    344        ir->array->as_dereference_array()) {
    345       /*          ir => foo[i][j]
    346        * inner_array => foo[i]
    347        */
    348       if (ir_dereference_variable * const deref_var =
    349           inner_array->array->as_dereference_variable()) {
    350          if (is_multiple_vertices(this->shader_stage, deref_var->var)) {
    351             /* foo is a geometry or tessellation shader input, so i is
    352              * the vertex, and j the part of the input we're accessing.
    353              */
    354             if (try_mark_partial_variable(deref_var->var, ir->array_index))
    355             {
    356                /* We've now taken care of foo and j, but i might contain a
    357                 * subexpression that accesses shader inputs.  So manually
    358                 * visit i and then continue with the parent.
    359                 */
    360                inner_array->array_index->accept(this);
    361                return visit_continue_with_parent;
    362             }
    363          }
    364       }
    365    } else if (ir_dereference_variable * const deref_var =
    366               ir->array->as_dereference_variable()) {
    367       /* ir => foo[i], where foo is a variable. */
    368       if (is_multiple_vertices(this->shader_stage, deref_var->var)) {
    369          /* foo is a geometry or tessellation shader input, so i is
    370           * the vertex, and we're accessing the entire input.
    371           */
    372          mark_whole_variable(deref_var->var);
    373          /* We've now taken care of foo, but i might contain a subexpression
    374           * that accesses shader inputs.  So manually visit i and then
    375           * continue with the parent.
    376           */
    377          ir->array_index->accept(this);
    378          return visit_continue_with_parent;
    379       } else if (is_shader_inout(deref_var->var)) {
    380          /* foo is a shader input/output, but not a geometry shader input,
    381           * so i is the part of the input we're accessing.
    382           */
    383          if (try_mark_partial_variable(deref_var->var, ir->array_index))
    384             return visit_continue_with_parent;
    385       }
    386    }
    387 
    388    /* The expression is something we don't recognize.  Just visit its
    389     * subexpressions.
    390     */
    391    return visit_continue;
    392 }
    393 
    394 ir_visitor_status
    395 ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
    396 {
    397    /* We don't want to descend into the function parameters and
    398     * consider them as shader inputs or outputs.
    399     */
    400    visit_list_elements(this, &ir->body);
    401    return visit_continue_with_parent;
    402 }
    403 
    404 ir_visitor_status
    405 ir_set_program_inouts_visitor::visit_enter(ir_discard *)
    406 {
    407    /* discards are only allowed in fragment shaders. */
    408    assert(this->shader_stage == MESA_SHADER_FRAGMENT);
    409 
    410    prog->info.fs.uses_discard = true;
    411 
    412    return visit_continue;
    413 }
    414 
    415 ir_visitor_status
    416 ir_set_program_inouts_visitor::visit_enter(ir_texture *ir)
    417 {
    418    if (ir->op == ir_tg4)
    419       prog->info.uses_texture_gather = true;
    420    return visit_continue;
    421 }
    422 
    423 void
    424 do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
    425                       gl_shader_stage shader_stage)
    426 {
    427    ir_set_program_inouts_visitor v(prog, shader_stage);
    428 
    429    prog->info.inputs_read = 0;
    430    prog->info.outputs_written = 0;
    431    prog->SecondaryOutputsWritten = 0;
    432    prog->info.outputs_read = 0;
    433    prog->info.patch_inputs_read = 0;
    434    prog->info.patch_outputs_written = 0;
    435    prog->info.system_values_read = 0;
    436    if (shader_stage == MESA_SHADER_FRAGMENT) {
    437       prog->info.fs.uses_sample_qualifier = false;
    438       prog->info.fs.uses_discard = false;
    439    }
    440    visit_list_elements(&v, instructions);
    441 }
    442