Home | History | Annotate | Download | only in glsl
      1 /*
      2  * Copyright  2011 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_varyings_to_packed.cpp
     26  *
     27  * This lowering pass generates GLSL code that manually packs varyings into
     28  * vec4 slots, for the benefit of back-ends that don't support packed varyings
     29  * natively.
     30  *
     31  * For example, the following shader:
     32  *
     33  *   out mat3x2 foo;  // location=4, location_frac=0
     34  *   out vec3 bar[2]; // location=5, location_frac=2
     35  *
     36  *   main()
     37  *   {
     38  *     ...
     39  *   }
     40  *
     41  * Is rewritten to:
     42  *
     43  *   mat3x2 foo;
     44  *   vec3 bar[2];
     45  *   out vec4 packed4; // location=4, location_frac=0
     46  *   out vec4 packed5; // location=5, location_frac=0
     47  *   out vec4 packed6; // location=6, location_frac=0
     48  *
     49  *   main()
     50  *   {
     51  *     ...
     52  *     packed4.xy = foo[0];
     53  *     packed4.zw = foo[1];
     54  *     packed5.xy = foo[2];
     55  *     packed5.zw = bar[0].xy;
     56  *     packed6.x = bar[0].z;
     57  *     packed6.yzw = bar[1];
     58  *   }
     59  *
     60  * This lowering pass properly handles "double parking" of a varying vector
     61  * across two varying slots.  For example, in the code above, two of the
     62  * components of bar[0] are stored in packed5, and the remaining component is
     63  * stored in packed6.
     64  *
     65  * Note that in theory, the extra instructions may cause some loss of
     66  * performance.  However, hopefully in most cases the performance loss will
     67  * either be absorbed by a later optimization pass, or it will be offset by
     68  * memory bandwidth savings (because fewer varyings are used).
     69  *
     70  * This lowering pass also packs flat floats, ints, and uints together, by
     71  * using ivec4 as the base type of flat "varyings", and using appropriate
     72  * casts to convert floats and uints into ints.
     73  *
     74  * This lowering pass also handles varyings whose type is a struct or an array
     75  * of struct.  Structs are packed in order and with no gaps, so there may be a
     76  * performance penalty due to structure elements being double-parked.
     77  *
     78  * Lowering of geometry shader inputs is slightly more complex, since geometry
     79  * inputs are always arrays, so we need to lower arrays to arrays.  For
     80  * example, the following input:
     81  *
     82  *   in struct Foo {
     83  *     float f;
     84  *     vec3 v;
     85  *     vec2 a[2];
     86  *   } arr[3];         // location=4, location_frac=0
     87  *
     88  * Would get lowered like this if it occurred in a fragment shader:
     89  *
     90  *   struct Foo {
     91  *     float f;
     92  *     vec3 v;
     93  *     vec2 a[2];
     94  *   } arr[3];
     95  *   in vec4 packed4;  // location=4, location_frac=0
     96  *   in vec4 packed5;  // location=5, location_frac=0
     97  *   in vec4 packed6;  // location=6, location_frac=0
     98  *   in vec4 packed7;  // location=7, location_frac=0
     99  *   in vec4 packed8;  // location=8, location_frac=0
    100  *   in vec4 packed9;  // location=9, location_frac=0
    101  *
    102  *   main()
    103  *   {
    104  *     arr[0].f = packed4.x;
    105  *     arr[0].v = packed4.yzw;
    106  *     arr[0].a[0] = packed5.xy;
    107  *     arr[0].a[1] = packed5.zw;
    108  *     arr[1].f = packed6.x;
    109  *     arr[1].v = packed6.yzw;
    110  *     arr[1].a[0] = packed7.xy;
    111  *     arr[1].a[1] = packed7.zw;
    112  *     arr[2].f = packed8.x;
    113  *     arr[2].v = packed8.yzw;
    114  *     arr[2].a[0] = packed9.xy;
    115  *     arr[2].a[1] = packed9.zw;
    116  *     ...
    117  *   }
    118  *
    119  * But it would get lowered like this if it occurred in a geometry shader:
    120  *
    121  *   struct Foo {
    122  *     float f;
    123  *     vec3 v;
    124  *     vec2 a[2];
    125  *   } arr[3];
    126  *   in vec4 packed4[3];  // location=4, location_frac=0
    127  *   in vec4 packed5[3];  // location=5, location_frac=0
    128  *
    129  *   main()
    130  *   {
    131  *     arr[0].f = packed4[0].x;
    132  *     arr[0].v = packed4[0].yzw;
    133  *     arr[0].a[0] = packed5[0].xy;
    134  *     arr[0].a[1] = packed5[0].zw;
    135  *     arr[1].f = packed4[1].x;
    136  *     arr[1].v = packed4[1].yzw;
    137  *     arr[1].a[0] = packed5[1].xy;
    138  *     arr[1].a[1] = packed5[1].zw;
    139  *     arr[2].f = packed4[2].x;
    140  *     arr[2].v = packed4[2].yzw;
    141  *     arr[2].a[0] = packed5[2].xy;
    142  *     arr[2].a[1] = packed5[2].zw;
    143  *     ...
    144  *   }
    145  */
    146 
    147 #include "glsl_symbol_table.h"
    148 #include "ir.h"
    149 #include "ir_builder.h"
    150 #include "ir_optimization.h"
    151 #include "program/prog_instruction.h"
    152 
    153 using namespace ir_builder;
    154 
    155 namespace {
    156 
    157 /**
    158  * Visitor that performs varying packing.  For each varying declared in the
    159  * shader, this visitor determines whether it needs to be packed.  If so, it
    160  * demotes it to an ordinary global, creates new packed varyings, and
    161  * generates assignments to convert between the original varying and the
    162  * packed varying.
    163  */
    164 class lower_packed_varyings_visitor
    165 {
    166 public:
    167    lower_packed_varyings_visitor(void *mem_ctx,
    168                                  unsigned locations_used,
    169                                  const uint8_t *components,
    170                                  ir_variable_mode mode,
    171                                  unsigned gs_input_vertices,
    172                                  exec_list *out_instructions,
    173                                  exec_list *out_variables,
    174                                  bool disable_varying_packing,
    175                                  bool xfb_enabled);
    176 
    177    void run(struct gl_linked_shader *shader);
    178 
    179 private:
    180    void bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs);
    181    void bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs);
    182    unsigned lower_rvalue(ir_rvalue *rvalue, unsigned fine_location,
    183                          ir_variable *unpacked_var, const char *name,
    184                          bool gs_input_toplevel, unsigned vertex_index);
    185    unsigned lower_arraylike(ir_rvalue *rvalue, unsigned array_size,
    186                             unsigned fine_location,
    187                             ir_variable *unpacked_var, const char *name,
    188                             bool gs_input_toplevel, unsigned vertex_index);
    189    ir_dereference *get_packed_varying_deref(unsigned location,
    190                                             ir_variable *unpacked_var,
    191                                             const char *name,
    192                                             unsigned vertex_index);
    193    bool needs_lowering(ir_variable *var);
    194 
    195    /**
    196     * Memory context used to allocate new instructions for the shader.
    197     */
    198    void * const mem_ctx;
    199 
    200    /**
    201     * Number of generic varying slots which are used by this shader.  This is
    202     * used to allocate temporary intermediate data structures.  If any varying
    203     * used by this shader has a location greater than or equal to
    204     * VARYING_SLOT_VAR0 + locations_used, an assertion will fire.
    205     */
    206    const unsigned locations_used;
    207 
    208    const uint8_t* components;
    209 
    210    /**
    211     * Array of pointers to the packed varyings that have been created for each
    212     * generic varying slot.  NULL entries in this array indicate varying slots
    213     * for which a packed varying has not been created yet.
    214     */
    215    ir_variable **packed_varyings;
    216 
    217    /**
    218     * Type of varying which is being lowered in this pass (either
    219     * ir_var_shader_in or ir_var_shader_out).
    220     */
    221    const ir_variable_mode mode;
    222 
    223    /**
    224     * If we are currently lowering geometry shader inputs, the number of input
    225     * vertices the geometry shader accepts.  Otherwise zero.
    226     */
    227    const unsigned gs_input_vertices;
    228 
    229    /**
    230     * Exec list into which the visitor should insert the packing instructions.
    231     * Caller provides this list; it should insert the instructions into the
    232     * appropriate place in the shader once the visitor has finished running.
    233     */
    234    exec_list *out_instructions;
    235 
    236    /**
    237     * Exec list into which the visitor should insert any new variables.
    238     */
    239    exec_list *out_variables;
    240 
    241    bool disable_varying_packing;
    242    bool xfb_enabled;
    243 };
    244 
    245 } /* anonymous namespace */
    246 
    247 lower_packed_varyings_visitor::lower_packed_varyings_visitor(
    248       void *mem_ctx, unsigned locations_used, const uint8_t *components,
    249       ir_variable_mode mode,
    250       unsigned gs_input_vertices, exec_list *out_instructions,
    251       exec_list *out_variables, bool disable_varying_packing,
    252       bool xfb_enabled)
    253    : mem_ctx(mem_ctx),
    254      locations_used(locations_used),
    255      components(components),
    256      packed_varyings((ir_variable **)
    257                      rzalloc_array_size(mem_ctx, sizeof(*packed_varyings),
    258                                         locations_used)),
    259      mode(mode),
    260      gs_input_vertices(gs_input_vertices),
    261      out_instructions(out_instructions),
    262      out_variables(out_variables),
    263      disable_varying_packing(disable_varying_packing),
    264      xfb_enabled(xfb_enabled)
    265 {
    266 }
    267 
    268 void
    269 lower_packed_varyings_visitor::run(struct gl_linked_shader *shader)
    270 {
    271    foreach_in_list(ir_instruction, node, shader->ir) {
    272       ir_variable *var = node->as_variable();
    273       if (var == NULL)
    274          continue;
    275 
    276       if (var->data.mode != this->mode ||
    277           var->data.location < VARYING_SLOT_VAR0 ||
    278           !this->needs_lowering(var))
    279          continue;
    280 
    281       /* This lowering pass is only capable of packing floats and ints
    282        * together when their interpolation mode is "flat".  Treat integers as
    283        * being flat when the interpolation mode is none.
    284        */
    285       assert(var->data.interpolation == INTERP_MODE_FLAT ||
    286              var->data.interpolation == INTERP_MODE_NONE ||
    287              !var->type->contains_integer());
    288 
    289       /* Clone the variable for program resource list before
    290        * it gets modified and lost.
    291        */
    292       if (!shader->packed_varyings)
    293          shader->packed_varyings = new (shader) exec_list;
    294 
    295       shader->packed_varyings->push_tail(var->clone(shader, NULL));
    296 
    297       /* Change the old varying into an ordinary global. */
    298       assert(var->data.mode != ir_var_temporary);
    299       var->data.mode = ir_var_auto;
    300 
    301       /* Create a reference to the old varying. */
    302       ir_dereference_variable *deref
    303          = new(this->mem_ctx) ir_dereference_variable(var);
    304 
    305       /* Recursively pack or unpack it. */
    306       this->lower_rvalue(deref, var->data.location * 4 + var->data.location_frac, var,
    307                          var->name, this->gs_input_vertices != 0, 0);
    308    }
    309 }
    310 
    311 #define SWIZZLE_ZWZW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W)
    312 
    313 /**
    314  * Make an ir_assignment from \c rhs to \c lhs, performing appropriate
    315  * bitcasts if necessary to match up types.
    316  *
    317  * This function is called when packing varyings.
    318  */
    319 void
    320 lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs,
    321                                                    ir_rvalue *rhs)
    322 {
    323    if (lhs->type->base_type != rhs->type->base_type) {
    324       /* Since we only mix types in flat varyings, and we always store flat
    325        * varyings as type ivec4, we need only produce conversions from (uint
    326        * or float) to int.
    327        */
    328       assert(lhs->type->base_type == GLSL_TYPE_INT);
    329       switch (rhs->type->base_type) {
    330       case GLSL_TYPE_UINT:
    331          rhs = new(this->mem_ctx)
    332             ir_expression(ir_unop_u2i, lhs->type, rhs);
    333          break;
    334       case GLSL_TYPE_FLOAT:
    335          rhs = new(this->mem_ctx)
    336             ir_expression(ir_unop_bitcast_f2i, lhs->type, rhs);
    337          break;
    338       case GLSL_TYPE_DOUBLE:
    339          assert(rhs->type->vector_elements <= 2);
    340          if (rhs->type->vector_elements == 2) {
    341             ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "pack", ir_var_temporary);
    342 
    343             assert(lhs->type->vector_elements == 4);
    344             this->out_variables->push_tail(t);
    345             this->out_instructions->push_tail(
    346                   assign(t, u2i(expr(ir_unop_unpack_double_2x32, swizzle_x(rhs->clone(mem_ctx, NULL)))), 0x3));
    347             this->out_instructions->push_tail(
    348                   assign(t,  u2i(expr(ir_unop_unpack_double_2x32, swizzle_y(rhs))), 0xc));
    349             rhs = deref(t).val;
    350          } else {
    351             rhs = u2i(expr(ir_unop_unpack_double_2x32, rhs));
    352          }
    353          break;
    354       default:
    355          assert(!"Unexpected type conversion while lowering varyings");
    356          break;
    357       }
    358    }
    359    this->out_instructions->push_tail(new (this->mem_ctx) ir_assignment(lhs, rhs));
    360 }
    361 
    362 
    363 /**
    364  * Make an ir_assignment from \c rhs to \c lhs, performing appropriate
    365  * bitcasts if necessary to match up types.
    366  *
    367  * This function is called when unpacking varyings.
    368  */
    369 void
    370 lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs,
    371                                                      ir_rvalue *rhs)
    372 {
    373    if (lhs->type->base_type != rhs->type->base_type) {
    374       /* Since we only mix types in flat varyings, and we always store flat
    375        * varyings as type ivec4, we need only produce conversions from int to
    376        * (uint or float).
    377        */
    378       assert(rhs->type->base_type == GLSL_TYPE_INT);
    379       switch (lhs->type->base_type) {
    380       case GLSL_TYPE_UINT:
    381          rhs = new(this->mem_ctx)
    382             ir_expression(ir_unop_i2u, lhs->type, rhs);
    383          break;
    384       case GLSL_TYPE_FLOAT:
    385          rhs = new(this->mem_ctx)
    386             ir_expression(ir_unop_bitcast_i2f, lhs->type, rhs);
    387          break;
    388       case GLSL_TYPE_DOUBLE:
    389          assert(lhs->type->vector_elements <= 2);
    390          if (lhs->type->vector_elements == 2) {
    391             ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "unpack", ir_var_temporary);
    392             assert(rhs->type->vector_elements == 4);
    393             this->out_variables->push_tail(t);
    394             this->out_instructions->push_tail(
    395                   assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle_xy(rhs->clone(mem_ctx, NULL)))), 0x1));
    396             this->out_instructions->push_tail(
    397                   assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle(rhs->clone(mem_ctx, NULL), SWIZZLE_ZWZW, 2))), 0x2));
    398             rhs = deref(t).val;
    399          } else {
    400             rhs = expr(ir_unop_pack_double_2x32, i2u(rhs));
    401          }
    402          break;
    403       default:
    404          assert(!"Unexpected type conversion while lowering varyings");
    405          break;
    406       }
    407    }
    408    this->out_instructions->push_tail(new(this->mem_ctx) ir_assignment(lhs, rhs));
    409 }
    410 
    411 
    412 /**
    413  * Recursively pack or unpack the given varying (or portion of a varying) by
    414  * traversing all of its constituent vectors.
    415  *
    416  * \param fine_location is the location where the first constituent vector
    417  * should be packed--the word "fine" indicates that this location is expressed
    418  * in multiples of a float, rather than multiples of a vec4 as is used
    419  * elsewhere in Mesa.
    420  *
    421  * \param gs_input_toplevel should be set to true if we are lowering geometry
    422  * shader inputs, and we are currently lowering the whole input variable
    423  * (i.e. we are lowering the array whose index selects the vertex).
    424  *
    425  * \param vertex_index: if we are lowering geometry shader inputs, and the
    426  * level of the array that we are currently lowering is *not* the top level,
    427  * then this indicates which vertex we are currently lowering.  Otherwise it
    428  * is ignored.
    429  *
    430  * \return the location where the next constituent vector (after this one)
    431  * should be packed.
    432  */
    433 unsigned
    434 lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
    435                                             unsigned fine_location,
    436                                             ir_variable *unpacked_var,
    437                                             const char *name,
    438                                             bool gs_input_toplevel,
    439                                             unsigned vertex_index)
    440 {
    441    unsigned dmul = rvalue->type->is_64bit() ? 2 : 1;
    442    /* When gs_input_toplevel is set, we should be looking at a geometry shader
    443     * input array.
    444     */
    445    assert(!gs_input_toplevel || rvalue->type->is_array());
    446 
    447    if (rvalue->type->is_record()) {
    448       for (unsigned i = 0; i < rvalue->type->length; i++) {
    449          if (i != 0)
    450             rvalue = rvalue->clone(this->mem_ctx, NULL);
    451          const char *field_name = rvalue->type->fields.structure[i].name;
    452          ir_dereference_record *dereference_record = new(this->mem_ctx)
    453             ir_dereference_record(rvalue, field_name);
    454          char *deref_name
    455             = ralloc_asprintf(this->mem_ctx, "%s.%s", name, field_name);
    456          fine_location = this->lower_rvalue(dereference_record, fine_location,
    457                                             unpacked_var, deref_name, false,
    458                                             vertex_index);
    459       }
    460       return fine_location;
    461    } else if (rvalue->type->is_array()) {
    462       /* Arrays are packed/unpacked by considering each array element in
    463        * sequence.
    464        */
    465       return this->lower_arraylike(rvalue, rvalue->type->array_size(),
    466                                    fine_location, unpacked_var, name,
    467                                    gs_input_toplevel, vertex_index);
    468    } else if (rvalue->type->is_matrix()) {
    469       /* Matrices are packed/unpacked by considering each column vector in
    470        * sequence.
    471        */
    472       return this->lower_arraylike(rvalue, rvalue->type->matrix_columns,
    473                                    fine_location, unpacked_var, name,
    474                                    false, vertex_index);
    475    } else if (rvalue->type->vector_elements * dmul +
    476               fine_location % 4 > 4) {
    477       /* This vector is going to be "double parked" across two varying slots,
    478        * so handle it as two separate assignments. For doubles, a dvec3/dvec4
    479        * can end up being spread over 3 slots. However the second splitting
    480        * will happen later, here we just always want to split into 2.
    481        */
    482       unsigned left_components, right_components;
    483       unsigned left_swizzle_values[4] = { 0, 0, 0, 0 };
    484       unsigned right_swizzle_values[4] = { 0, 0, 0, 0 };
    485       char left_swizzle_name[4] = { 0, 0, 0, 0 };
    486       char right_swizzle_name[4] = { 0, 0, 0, 0 };
    487 
    488       left_components = 4 - fine_location % 4;
    489       if (rvalue->type->is_64bit()) {
    490          /* We might actually end up with 0 left components! */
    491          left_components /= 2;
    492       }
    493       right_components = rvalue->type->vector_elements - left_components;
    494 
    495       for (unsigned i = 0; i < left_components; i++) {
    496          left_swizzle_values[i] = i;
    497          left_swizzle_name[i] = "xyzw"[i];
    498       }
    499       for (unsigned i = 0; i < right_components; i++) {
    500          right_swizzle_values[i] = i + left_components;
    501          right_swizzle_name[i] = "xyzw"[i + left_components];
    502       }
    503       ir_swizzle *left_swizzle = new(this->mem_ctx)
    504          ir_swizzle(rvalue, left_swizzle_values, left_components);
    505       ir_swizzle *right_swizzle = new(this->mem_ctx)
    506          ir_swizzle(rvalue->clone(this->mem_ctx, NULL), right_swizzle_values,
    507                     right_components);
    508       char *left_name
    509          = ralloc_asprintf(this->mem_ctx, "%s.%s", name, left_swizzle_name);
    510       char *right_name
    511          = ralloc_asprintf(this->mem_ctx, "%s.%s", name, right_swizzle_name);
    512       if (left_components)
    513          fine_location = this->lower_rvalue(left_swizzle, fine_location,
    514                                             unpacked_var, left_name, false,
    515                                             vertex_index);
    516       else
    517          /* Top up the fine location to the next slot */
    518          fine_location++;
    519       return this->lower_rvalue(right_swizzle, fine_location, unpacked_var,
    520                                 right_name, false, vertex_index);
    521    } else {
    522       /* No special handling is necessary; pack the rvalue into the
    523        * varying.
    524        */
    525       unsigned swizzle_values[4] = { 0, 0, 0, 0 };
    526       unsigned components = rvalue->type->vector_elements * dmul;
    527       unsigned location = fine_location / 4;
    528       unsigned location_frac = fine_location % 4;
    529       for (unsigned i = 0; i < components; ++i)
    530          swizzle_values[i] = i + location_frac;
    531       ir_dereference *packed_deref =
    532          this->get_packed_varying_deref(location, unpacked_var, name,
    533                                         vertex_index);
    534       if (unpacked_var->data.stream != 0) {
    535          assert(unpacked_var->data.stream < 4);
    536          ir_variable *packed_var = packed_deref->variable_referenced();
    537          for (unsigned i = 0; i < components; ++i) {
    538             packed_var->data.stream |=
    539                unpacked_var->data.stream << (2 * (location_frac + i));
    540          }
    541       }
    542       ir_swizzle *swizzle = new(this->mem_ctx)
    543          ir_swizzle(packed_deref, swizzle_values, components);
    544       if (this->mode == ir_var_shader_out) {
    545          this->bitwise_assign_pack(swizzle, rvalue);
    546       } else {
    547          this->bitwise_assign_unpack(rvalue, swizzle);
    548       }
    549       return fine_location + components;
    550    }
    551 }
    552 
    553 /**
    554  * Recursively pack or unpack a varying for which we need to iterate over its
    555  * constituent elements, accessing each one using an ir_dereference_array.
    556  * This takes care of both arrays and matrices, since ir_dereference_array
    557  * treats a matrix like an array of its column vectors.
    558  *
    559  * \param gs_input_toplevel should be set to true if we are lowering geometry
    560  * shader inputs, and we are currently lowering the whole input variable
    561  * (i.e. we are lowering the array whose index selects the vertex).
    562  *
    563  * \param vertex_index: if we are lowering geometry shader inputs, and the
    564  * level of the array that we are currently lowering is *not* the top level,
    565  * then this indicates which vertex we are currently lowering.  Otherwise it
    566  * is ignored.
    567  */
    568 unsigned
    569 lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue,
    570                                                unsigned array_size,
    571                                                unsigned fine_location,
    572                                                ir_variable *unpacked_var,
    573                                                const char *name,
    574                                                bool gs_input_toplevel,
    575                                                unsigned vertex_index)
    576 {
    577    for (unsigned i = 0; i < array_size; i++) {
    578       if (i != 0)
    579          rvalue = rvalue->clone(this->mem_ctx, NULL);
    580       ir_constant *constant = new(this->mem_ctx) ir_constant(i);
    581       ir_dereference_array *dereference_array = new(this->mem_ctx)
    582          ir_dereference_array(rvalue, constant);
    583       if (gs_input_toplevel) {
    584          /* Geometry shader inputs are a special case.  Instead of storing
    585           * each element of the array at a different location, all elements
    586           * are at the same location, but with a different vertex index.
    587           */
    588          (void) this->lower_rvalue(dereference_array, fine_location,
    589                                    unpacked_var, name, false, i);
    590       } else {
    591          char *subscripted_name
    592             = ralloc_asprintf(this->mem_ctx, "%s[%d]", name, i);
    593          fine_location =
    594             this->lower_rvalue(dereference_array, fine_location,
    595                                unpacked_var, subscripted_name,
    596                                false, vertex_index);
    597       }
    598    }
    599    return fine_location;
    600 }
    601 
    602 /**
    603  * Retrieve the packed varying corresponding to the given varying location.
    604  * If no packed varying has been created for the given varying location yet,
    605  * create it and add it to the shader before returning it.
    606  *
    607  * The newly created varying inherits its interpolation parameters from \c
    608  * unpacked_var.  Its base type is ivec4 if we are lowering a flat varying,
    609  * vec4 otherwise.
    610  *
    611  * \param vertex_index: if we are lowering geometry shader inputs, then this
    612  * indicates which vertex we are currently lowering.  Otherwise it is ignored.
    613  */
    614 ir_dereference *
    615 lower_packed_varyings_visitor::get_packed_varying_deref(
    616       unsigned location, ir_variable *unpacked_var, const char *name,
    617       unsigned vertex_index)
    618 {
    619    unsigned slot = location - VARYING_SLOT_VAR0;
    620    assert(slot < locations_used);
    621    if (this->packed_varyings[slot] == NULL) {
    622       char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name);
    623       const glsl_type *packed_type;
    624       assert(components[slot] != 0);
    625       if (unpacked_var->is_interpolation_flat())
    626          packed_type = glsl_type::get_instance(GLSL_TYPE_INT, components[slot], 1);
    627       else
    628          packed_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, components[slot], 1);
    629       if (this->gs_input_vertices != 0) {
    630          packed_type =
    631             glsl_type::get_array_instance(packed_type,
    632                                           this->gs_input_vertices);
    633       }
    634       ir_variable *packed_var = new(this->mem_ctx)
    635          ir_variable(packed_type, packed_name, this->mode);
    636       if (this->gs_input_vertices != 0) {
    637          /* Prevent update_array_sizes() from messing with the size of the
    638           * array.
    639           */
    640          packed_var->data.max_array_access = this->gs_input_vertices - 1;
    641       }
    642       packed_var->data.centroid = unpacked_var->data.centroid;
    643       packed_var->data.sample = unpacked_var->data.sample;
    644       packed_var->data.patch = unpacked_var->data.patch;
    645       packed_var->data.interpolation = packed_type == glsl_type::ivec4_type
    646          ? unsigned(INTERP_MODE_FLAT) : unpacked_var->data.interpolation;
    647       packed_var->data.location = location;
    648       packed_var->data.precision = unpacked_var->data.precision;
    649       packed_var->data.always_active_io = unpacked_var->data.always_active_io;
    650       packed_var->data.stream = 1u << 31;
    651       unpacked_var->insert_before(packed_var);
    652       this->packed_varyings[slot] = packed_var;
    653    } else {
    654       /* For geometry shader inputs, only update the packed variable name the
    655        * first time we visit each component.
    656        */
    657       if (this->gs_input_vertices == 0 || vertex_index == 0) {
    658          ir_variable *var = this->packed_varyings[slot];
    659 
    660          if (var->is_name_ralloced())
    661             ralloc_asprintf_append((char **) &var->name, ",%s", name);
    662          else
    663             var->name = ralloc_asprintf(var, "%s,%s", var->name, name);
    664       }
    665    }
    666 
    667    ir_dereference *deref = new(this->mem_ctx)
    668       ir_dereference_variable(this->packed_varyings[slot]);
    669    if (this->gs_input_vertices != 0) {
    670       /* When lowering GS inputs, the packed variable is an array, so we need
    671        * to dereference it using vertex_index.
    672        */
    673       ir_constant *constant = new(this->mem_ctx) ir_constant(vertex_index);
    674       deref = new(this->mem_ctx) ir_dereference_array(deref, constant);
    675    }
    676    return deref;
    677 }
    678 
    679 bool
    680 lower_packed_varyings_visitor::needs_lowering(ir_variable *var)
    681 {
    682    /* Things composed of vec4's and varyings with explicitly assigned
    683     * locations don't need lowering.  Everything else does.
    684     */
    685    if (var->data.explicit_location)
    686       return false;
    687 
    688    /* Override disable_varying_packing if the var is only used by transform
    689     * feedback. Also override it if transform feedback is enabled and the
    690     * variable is an array, struct or matrix as the elements of these types
    691     * will always has the same interpolation and therefore asre safe to pack.
    692     */
    693    const glsl_type *type = var->type;
    694    if (disable_varying_packing && !var->data.is_xfb_only &&
    695        !((type->is_array() || type->is_record() || type->is_matrix()) &&
    696          xfb_enabled))
    697       return false;
    698 
    699    type = type->without_array();
    700    if (type->vector_elements == 4 && !type->is_64bit())
    701       return false;
    702    return true;
    703 }
    704 
    705 
    706 /**
    707  * Visitor that splices varying packing code before every use of EmitVertex()
    708  * in a geometry shader.
    709  */
    710 class lower_packed_varyings_gs_splicer : public ir_hierarchical_visitor
    711 {
    712 public:
    713    explicit lower_packed_varyings_gs_splicer(void *mem_ctx,
    714                                              const exec_list *instructions);
    715 
    716    virtual ir_visitor_status visit_leave(ir_emit_vertex *ev);
    717 
    718 private:
    719    /**
    720     * Memory context used to allocate new instructions for the shader.
    721     */
    722    void * const mem_ctx;
    723 
    724    /**
    725     * Instructions that should be spliced into place before each EmitVertex()
    726     * call.
    727     */
    728    const exec_list *instructions;
    729 };
    730 
    731 
    732 lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer(
    733       void *mem_ctx, const exec_list *instructions)
    734    : mem_ctx(mem_ctx), instructions(instructions)
    735 {
    736 }
    737 
    738 
    739 ir_visitor_status
    740 lower_packed_varyings_gs_splicer::visit_leave(ir_emit_vertex *ev)
    741 {
    742    foreach_in_list(ir_instruction, ir, this->instructions) {
    743       ev->insert_before(ir->clone(this->mem_ctx, NULL));
    744    }
    745    return visit_continue;
    746 }
    747 
    748 /**
    749  * Visitor that splices varying packing code before every return.
    750  */
    751 class lower_packed_varyings_return_splicer : public ir_hierarchical_visitor
    752 {
    753 public:
    754    explicit lower_packed_varyings_return_splicer(void *mem_ctx,
    755                                                  const exec_list *instructions);
    756 
    757    virtual ir_visitor_status visit_leave(ir_return *ret);
    758 
    759 private:
    760    /**
    761     * Memory context used to allocate new instructions for the shader.
    762     */
    763    void * const mem_ctx;
    764 
    765    /**
    766     * Instructions that should be spliced into place before each return.
    767     */
    768    const exec_list *instructions;
    769 };
    770 
    771 
    772 lower_packed_varyings_return_splicer::lower_packed_varyings_return_splicer(
    773       void *mem_ctx, const exec_list *instructions)
    774    : mem_ctx(mem_ctx), instructions(instructions)
    775 {
    776 }
    777 
    778 
    779 ir_visitor_status
    780 lower_packed_varyings_return_splicer::visit_leave(ir_return *ret)
    781 {
    782    foreach_in_list(ir_instruction, ir, this->instructions) {
    783       ret->insert_before(ir->clone(this->mem_ctx, NULL));
    784    }
    785    return visit_continue;
    786 }
    787 
    788 void
    789 lower_packed_varyings(void *mem_ctx, unsigned locations_used,
    790                       const uint8_t *components,
    791                       ir_variable_mode mode, unsigned gs_input_vertices,
    792                       gl_linked_shader *shader, bool disable_varying_packing,
    793                       bool xfb_enabled)
    794 {
    795    exec_list *instructions = shader->ir;
    796    ir_function *main_func = shader->symbols->get_function("main");
    797    exec_list void_parameters;
    798    ir_function_signature *main_func_sig
    799       = main_func->matching_signature(NULL, &void_parameters, false);
    800    exec_list new_instructions, new_variables;
    801    lower_packed_varyings_visitor visitor(mem_ctx,
    802                                          locations_used,
    803                                          components,
    804                                          mode,
    805                                          gs_input_vertices,
    806                                          &new_instructions,
    807                                          &new_variables,
    808                                          disable_varying_packing,
    809                                          xfb_enabled);
    810    visitor.run(shader);
    811    if (mode == ir_var_shader_out) {
    812       if (shader->Stage == MESA_SHADER_GEOMETRY) {
    813          /* For geometry shaders, outputs need to be lowered before each call
    814           * to EmitVertex()
    815           */
    816          lower_packed_varyings_gs_splicer splicer(mem_ctx, &new_instructions);
    817 
    818          /* Add all the variables in first. */
    819          main_func_sig->body.get_head_raw()->insert_before(&new_variables);
    820 
    821          /* Now update all the EmitVertex instances */
    822          splicer.run(instructions);
    823       } else {
    824          /* For other shader types, outputs need to be lowered before each
    825           * return statement and at the end of main()
    826           */
    827 
    828          lower_packed_varyings_return_splicer splicer(mem_ctx, &new_instructions);
    829 
    830          main_func_sig->body.get_head_raw()->insert_before(&new_variables);
    831 
    832          splicer.run(instructions);
    833 
    834          /* Lower outputs at the end of main() if the last instruction is not
    835           * a return statement
    836           */
    837          if (((ir_instruction*)instructions->get_tail())->ir_type != ir_type_return) {
    838             main_func_sig->body.append_list(&new_instructions);
    839          }
    840       }
    841    } else {
    842       /* Shader inputs need to be lowered at the beginning of main() */
    843       main_func_sig->body.get_head_raw()->insert_before(&new_instructions);
    844       main_func_sig->body.get_head_raw()->insert_before(&new_variables);
    845    }
    846 }
    847