Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2012 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 link_varyings.cpp
  26.  *
  27.  * Linker functions related specifically to linking varyings between shader
  28.  * stages.
  29.  */
  30.  
  31.  
  32. #include "main/mtypes.h"
  33. #include "glsl_symbol_table.h"
  34. #include "glsl_parser_extras.h"
  35. #include "ir_optimization.h"
  36. #include "linker.h"
  37. #include "link_varyings.h"
  38. #include "main/macros.h"
  39. #include "program/hash_table.h"
  40. #include "program.h"
  41.  
  42.  
  43. /**
  44.  * Validate that outputs from one stage match inputs of another
  45.  */
  46. bool
  47. cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
  48.                                  gl_shader *producer, gl_shader *consumer)
  49. {
  50.    glsl_symbol_table parameters;
  51.    const char *const producer_stage =
  52.       _mesa_glsl_shader_target_name(producer->Type);
  53.    const char *const consumer_stage =
  54.       _mesa_glsl_shader_target_name(consumer->Type);
  55.  
  56.    /* Find all shader outputs in the "producer" stage.
  57.     */
  58.    foreach_list(node, producer->ir) {
  59.       ir_variable *const var = ((ir_instruction *) node)->as_variable();
  60.  
  61.       if ((var == NULL) || (var->mode != ir_var_shader_out))
  62.          continue;
  63.  
  64.       parameters.add_variable(var);
  65.    }
  66.  
  67.  
  68.    /* Find all shader inputs in the "consumer" stage.  Any variables that have
  69.     * matching outputs already in the symbol table must have the same type and
  70.     * qualifiers.
  71.     */
  72.    foreach_list(node, consumer->ir) {
  73.       ir_variable *const input = ((ir_instruction *) node)->as_variable();
  74.  
  75.       if ((input == NULL) || (input->mode != ir_var_shader_in))
  76.          continue;
  77.  
  78.       ir_variable *const output = parameters.get_variable(input->name);
  79.       if (output != NULL) {
  80.          /* Check that the types match between stages.
  81.           */
  82.          if (input->type != output->type) {
  83.             /* There is a bit of a special case for gl_TexCoord.  This
  84.              * built-in is unsized by default.  Applications that variable
  85.              * access it must redeclare it with a size.  There is some
  86.              * language in the GLSL spec that implies the fragment shader
  87.              * and vertex shader do not have to agree on this size.  Other
  88.              * driver behave this way, and one or two applications seem to
  89.              * rely on it.
  90.              *
  91.              * Neither declaration needs to be modified here because the array
  92.              * sizes are fixed later when update_array_sizes is called.
  93.              *
  94.              * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec:
  95.              *
  96.              *     "Unlike user-defined varying variables, the built-in
  97.              *     varying variables don't have a strict one-to-one
  98.              *     correspondence between the vertex language and the
  99.              *     fragment language."
  100.              */
  101.             if (!output->type->is_array()
  102.                 || (strncmp("gl_", output->name, 3) != 0)) {
  103.                linker_error(prog,
  104.                             "%s shader output `%s' declared as type `%s', "
  105.                             "but %s shader input declared as type `%s'\n",
  106.                             producer_stage, output->name,
  107.                             output->type->name,
  108.                             consumer_stage, input->type->name);
  109.                return false;
  110.             }
  111.          }
  112.  
  113.          /* Check that all of the qualifiers match between stages.
  114.           */
  115.          if (input->centroid != output->centroid) {
  116.             linker_error(prog,
  117.                          "%s shader output `%s' %s centroid qualifier, "
  118.                          "but %s shader input %s centroid qualifier\n",
  119.                          producer_stage,
  120.                          output->name,
  121.                          (output->centroid) ? "has" : "lacks",
  122.                          consumer_stage,
  123.                          (input->centroid) ? "has" : "lacks");
  124.             return false;
  125.          }
  126.  
  127.          if (input->invariant != output->invariant) {
  128.             linker_error(prog,
  129.                          "%s shader output `%s' %s invariant qualifier, "
  130.                          "but %s shader input %s invariant qualifier\n",
  131.                          producer_stage,
  132.                          output->name,
  133.                          (output->invariant) ? "has" : "lacks",
  134.                          consumer_stage,
  135.                          (input->invariant) ? "has" : "lacks");
  136.             return false;
  137.          }
  138.  
  139.          if (input->interpolation != output->interpolation) {
  140.             linker_error(prog,
  141.                          "%s shader output `%s' specifies %s "
  142.                          "interpolation qualifier, "
  143.                          "but %s shader input specifies %s "
  144.                          "interpolation qualifier\n",
  145.                          producer_stage,
  146.                          output->name,
  147.                          output->interpolation_string(),
  148.                          consumer_stage,
  149.                          input->interpolation_string());
  150.             return false;
  151.          }
  152.       }
  153.    }
  154.  
  155.    return true;
  156. }
  157.  
  158.  
  159. /**
  160.  * Initialize this object based on a string that was passed to
  161.  * glTransformFeedbackVaryings.
  162.  *
  163.  * If the input is mal-formed, this call still succeeds, but it sets
  164.  * this->var_name to a mal-formed input, so tfeedback_decl::find_output_var()
  165.  * will fail to find any matching variable.
  166.  */
  167. void
  168. tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
  169.                      const void *mem_ctx, const char *input)
  170. {
  171.    /* We don't have to be pedantic about what is a valid GLSL variable name,
  172.     * because any variable with an invalid name can't exist in the IR anyway.
  173.     */
  174.  
  175.    this->location = -1;
  176.    this->orig_name = input;
  177.    this->is_clip_distance_mesa = false;
  178.    this->skip_components = 0;
  179.    this->next_buffer_separator = false;
  180.    this->matched_candidate = NULL;
  181.  
  182.    if (ctx->Extensions.ARB_transform_feedback3) {
  183.       /* Parse gl_NextBuffer. */
  184.       if (strcmp(input, "gl_NextBuffer") == 0) {
  185.          this->next_buffer_separator = true;
  186.          return;
  187.       }
  188.  
  189.       /* Parse gl_SkipComponents. */
  190.       if (strcmp(input, "gl_SkipComponents1") == 0)
  191.          this->skip_components = 1;
  192.       else if (strcmp(input, "gl_SkipComponents2") == 0)
  193.          this->skip_components = 2;
  194.       else if (strcmp(input, "gl_SkipComponents3") == 0)
  195.          this->skip_components = 3;
  196.       else if (strcmp(input, "gl_SkipComponents4") == 0)
  197.          this->skip_components = 4;
  198.  
  199.       if (this->skip_components)
  200.          return;
  201.    }
  202.  
  203.    /* Parse a declaration. */
  204.    const char *base_name_end;
  205.    long subscript = parse_program_resource_name(input, &base_name_end);
  206.    this->var_name = ralloc_strndup(mem_ctx, input, base_name_end - input);
  207.    if (subscript >= 0) {
  208.       this->array_subscript = subscript;
  209.       this->is_subscripted = true;
  210.    } else {
  211.       this->is_subscripted = false;
  212.    }
  213.  
  214.    /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this
  215.     * class must behave specially to account for the fact that gl_ClipDistance
  216.     * is converted from a float[8] to a vec4[2].
  217.     */
  218.    if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
  219.        strcmp(this->var_name, "gl_ClipDistance") == 0) {
  220.       this->is_clip_distance_mesa = true;
  221.    }
  222. }
  223.  
  224.  
  225. /**
  226.  * Determine whether two tfeedback_decl objects refer to the same variable and
  227.  * array index (if applicable).
  228.  */
  229. bool
  230. tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
  231. {
  232.    assert(x.is_varying() && y.is_varying());
  233.  
  234.    if (strcmp(x.var_name, y.var_name) != 0)
  235.       return false;
  236.    if (x.is_subscripted != y.is_subscripted)
  237.       return false;
  238.    if (x.is_subscripted && x.array_subscript != y.array_subscript)
  239.       return false;
  240.    return true;
  241. }
  242.  
  243.  
  244. /**
  245.  * Assign a location for this tfeedback_decl object based on the transform
  246.  * feedback candidate found by find_candidate.
  247.  *
  248.  * If an error occurs, the error is reported through linker_error() and false
  249.  * is returned.
  250.  */
  251. bool
  252. tfeedback_decl::assign_location(struct gl_context *ctx,
  253.                                 struct gl_shader_program *prog)
  254. {
  255.    assert(this->is_varying());
  256.  
  257.    unsigned fine_location
  258.       = this->matched_candidate->toplevel_var->location * 4
  259.       + this->matched_candidate->toplevel_var->location_frac
  260.       + this->matched_candidate->offset;
  261.  
  262.    if (this->matched_candidate->type->is_array()) {
  263.       /* Array variable */
  264.       const unsigned matrix_cols =
  265.          this->matched_candidate->type->fields.array->matrix_columns;
  266.       const unsigned vector_elements =
  267.          this->matched_candidate->type->fields.array->vector_elements;
  268.       unsigned actual_array_size = this->is_clip_distance_mesa ?
  269.          prog->Vert.ClipDistanceArraySize :
  270.          this->matched_candidate->type->array_size();
  271.  
  272.       if (this->is_subscripted) {
  273.          /* Check array bounds. */
  274.          if (this->array_subscript >= actual_array_size) {
  275.             linker_error(prog, "Transform feedback varying %s has index "
  276.                          "%i, but the array size is %u.",
  277.                          this->orig_name, this->array_subscript,
  278.                          actual_array_size);
  279.             return false;
  280.          }
  281.          unsigned array_elem_size = this->is_clip_distance_mesa ?
  282.             1 : vector_elements * matrix_cols;
  283.          fine_location += array_elem_size * this->array_subscript;
  284.          this->size = 1;
  285.       } else {
  286.          this->size = actual_array_size;
  287.       }
  288.       this->vector_elements = vector_elements;
  289.       this->matrix_columns = matrix_cols;
  290.       if (this->is_clip_distance_mesa)
  291.          this->type = GL_FLOAT;
  292.       else
  293.          this->type = this->matched_candidate->type->fields.array->gl_type;
  294.    } else {
  295.       /* Regular variable (scalar, vector, or matrix) */
  296.       if (this->is_subscripted) {
  297.          linker_error(prog, "Transform feedback varying %s requested, "
  298.                       "but %s is not an array.",
  299.                       this->orig_name, this->var_name);
  300.          return false;
  301.       }
  302.       this->size = 1;
  303.       this->vector_elements = this->matched_candidate->type->vector_elements;
  304.       this->matrix_columns = this->matched_candidate->type->matrix_columns;
  305.       this->type = this->matched_candidate->type->gl_type;
  306.    }
  307.    this->location = fine_location / 4;
  308.    this->location_frac = fine_location % 4;
  309.  
  310.    /* From GL_EXT_transform_feedback:
  311.     *   A program will fail to link if:
  312.     *
  313.     *   * the total number of components to capture in any varying
  314.     *     variable in <varyings> is greater than the constant
  315.     *     MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT and the
  316.     *     buffer mode is SEPARATE_ATTRIBS_EXT;
  317.     */
  318.    if (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS &&
  319.        this->num_components() >
  320.        ctx->Const.MaxTransformFeedbackSeparateComponents) {
  321.       linker_error(prog, "Transform feedback varying %s exceeds "
  322.                    "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.",
  323.                    this->orig_name);
  324.       return false;
  325.    }
  326.  
  327.    return true;
  328. }
  329.  
  330.  
  331. unsigned
  332. tfeedback_decl::get_num_outputs() const
  333. {
  334.    if (!this->is_varying()) {
  335.       return 0;
  336.    }
  337.  
  338.    return (this->num_components() + this->location_frac + 3)/4;
  339. }
  340.  
  341.  
  342. /**
  343.  * Update gl_transform_feedback_info to reflect this tfeedback_decl.
  344.  *
  345.  * If an error occurs, the error is reported through linker_error() and false
  346.  * is returned.
  347.  */
  348. bool
  349. tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
  350.                       struct gl_transform_feedback_info *info,
  351.                       unsigned buffer, const unsigned max_outputs) const
  352. {
  353.    assert(!this->next_buffer_separator);
  354.  
  355.    /* Handle gl_SkipComponents. */
  356.    if (this->skip_components) {
  357.       info->BufferStride[buffer] += this->skip_components;
  358.       return true;
  359.    }
  360.  
  361.    /* From GL_EXT_transform_feedback:
  362.     *   A program will fail to link if:
  363.     *
  364.     *     * the total number of components to capture is greater than
  365.     *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
  366.     *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
  367.     */
  368.    if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
  369.        info->BufferStride[buffer] + this->num_components() >
  370.        ctx->Const.MaxTransformFeedbackInterleavedComponents) {
  371.       linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
  372.                    "limit has been exceeded.");
  373.       return false;
  374.    }
  375.  
  376.    unsigned location = this->location;
  377.    unsigned location_frac = this->location_frac;
  378.    unsigned num_components = this->num_components();
  379.    while (num_components > 0) {
  380.       unsigned output_size = MIN2(num_components, 4 - location_frac);
  381.       assert(info->NumOutputs < max_outputs);
  382.       info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
  383.       info->Outputs[info->NumOutputs].OutputRegister = location;
  384.       info->Outputs[info->NumOutputs].NumComponents = output_size;
  385.       info->Outputs[info->NumOutputs].OutputBuffer = buffer;
  386.       info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
  387.       ++info->NumOutputs;
  388.       info->BufferStride[buffer] += output_size;
  389.       num_components -= output_size;
  390.       location++;
  391.       location_frac = 0;
  392.    }
  393.  
  394.    info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
  395.    info->Varyings[info->NumVarying].Type = this->type;
  396.    info->Varyings[info->NumVarying].Size = this->size;
  397.    info->NumVarying++;
  398.  
  399.    return true;
  400. }
  401.  
  402.  
  403. const tfeedback_candidate *
  404. tfeedback_decl::find_candidate(gl_shader_program *prog,
  405.                                hash_table *tfeedback_candidates)
  406. {
  407.    const char *name = this->is_clip_distance_mesa
  408.       ? "gl_ClipDistanceMESA" : this->var_name;
  409.    this->matched_candidate = (const tfeedback_candidate *)
  410.       hash_table_find(tfeedback_candidates, name);
  411.    if (!this->matched_candidate) {
  412.       /* From GL_EXT_transform_feedback:
  413.        *   A program will fail to link if:
  414.        *
  415.        *   * any variable name specified in the <varyings> array is not
  416.        *     declared as an output in the geometry shader (if present) or
  417.        *     the vertex shader (if no geometry shader is present);
  418.        */
  419.       linker_error(prog, "Transform feedback varying %s undeclared.",
  420.                    this->orig_name);
  421.    }
  422.    return this->matched_candidate;
  423. }
  424.  
  425.  
  426. /**
  427.  * Parse all the transform feedback declarations that were passed to
  428.  * glTransformFeedbackVaryings() and store them in tfeedback_decl objects.
  429.  *
  430.  * If an error occurs, the error is reported through linker_error() and false
  431.  * is returned.
  432.  */
  433. bool
  434. parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
  435.                       const void *mem_ctx, unsigned num_names,
  436.                       char **varying_names, tfeedback_decl *decls)
  437. {
  438.    for (unsigned i = 0; i < num_names; ++i) {
  439.       decls[i].init(ctx, prog, mem_ctx, varying_names[i]);
  440.  
  441.       if (!decls[i].is_varying())
  442.          continue;
  443.  
  444.       /* From GL_EXT_transform_feedback:
  445.        *   A program will fail to link if:
  446.        *
  447.        *   * any two entries in the <varyings> array specify the same varying
  448.        *     variable;
  449.        *
  450.        * We interpret this to mean "any two entries in the <varyings> array
  451.        * specify the same varying variable and array index", since transform
  452.        * feedback of arrays would be useless otherwise.
  453.        */
  454.       for (unsigned j = 0; j < i; ++j) {
  455.          if (!decls[j].is_varying())
  456.             continue;
  457.  
  458.          if (tfeedback_decl::is_same(decls[i], decls[j])) {
  459.             linker_error(prog, "Transform feedback varying %s specified "
  460.                          "more than once.", varying_names[i]);
  461.             return false;
  462.          }
  463.       }
  464.    }
  465.    return true;
  466. }
  467.  
  468.  
  469. /**
  470.  * Store transform feedback location assignments into
  471.  * prog->LinkedTransformFeedback based on the data stored in tfeedback_decls.
  472.  *
  473.  * If an error occurs, the error is reported through linker_error() and false
  474.  * is returned.
  475.  */
  476. bool
  477. store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
  478.                      unsigned num_tfeedback_decls,
  479.                      tfeedback_decl *tfeedback_decls)
  480. {
  481.    bool separate_attribs_mode =
  482.       prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
  483.  
  484.    ralloc_free(prog->LinkedTransformFeedback.Varyings);
  485.    ralloc_free(prog->LinkedTransformFeedback.Outputs);
  486.  
  487.    memset(&prog->LinkedTransformFeedback, 0,
  488.           sizeof(prog->LinkedTransformFeedback));
  489.  
  490.    prog->LinkedTransformFeedback.Varyings =
  491.       rzalloc_array(prog,
  492.                     struct gl_transform_feedback_varying_info,
  493.                     num_tfeedback_decls);
  494.  
  495.    unsigned num_outputs = 0;
  496.    for (unsigned i = 0; i < num_tfeedback_decls; ++i)
  497.       num_outputs += tfeedback_decls[i].get_num_outputs();
  498.  
  499.    prog->LinkedTransformFeedback.Outputs =
  500.       rzalloc_array(prog,
  501.                     struct gl_transform_feedback_output,
  502.                     num_outputs);
  503.  
  504.    unsigned num_buffers = 0;
  505.  
  506.    if (separate_attribs_mode) {
  507.       /* GL_SEPARATE_ATTRIBS */
  508.       for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
  509.          if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
  510.                                        num_buffers, num_outputs))
  511.             return false;
  512.  
  513.          num_buffers++;
  514.       }
  515.    }
  516.    else {
  517.       /* GL_INVERLEAVED_ATTRIBS */
  518.       for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
  519.          if (tfeedback_decls[i].is_next_buffer_separator()) {
  520.             num_buffers++;
  521.             continue;
  522.          }
  523.  
  524.          if (!tfeedback_decls[i].store(ctx, prog,
  525.                                        &prog->LinkedTransformFeedback,
  526.                                        num_buffers, num_outputs))
  527.             return false;
  528.       }
  529.       num_buffers++;
  530.    }
  531.  
  532.    assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
  533.  
  534.    prog->LinkedTransformFeedback.NumBuffers = num_buffers;
  535.    return true;
  536. }
  537.  
  538.  
  539. /**
  540.  * Data structure recording the relationship between outputs of one shader
  541.  * stage (the "producer") and inputs of another (the "consumer").
  542.  */
  543. class varying_matches
  544. {
  545. public:
  546.    varying_matches(bool disable_varying_packing, bool consumer_is_fs);
  547.    ~varying_matches();
  548.    void record(ir_variable *producer_var, ir_variable *consumer_var);
  549.    unsigned assign_locations();
  550.    void store_locations(unsigned producer_base, unsigned consumer_base) const;
  551.  
  552. private:
  553.    /**
  554.     * If true, this driver disables varying packing, so all varyings need to
  555.     * be aligned on slot boundaries, and take up a number of slots equal to
  556.     * their number of matrix columns times their array size.
  557.     */
  558.    const bool disable_varying_packing;
  559.  
  560.    /**
  561.     * Enum representing the order in which varyings are packed within a
  562.     * packing class.
  563.     *
  564.     * Currently we pack vec4's first, then vec2's, then scalar values, then
  565.     * vec3's.  This order ensures that the only vectors that are at risk of
  566.     * having to be "double parked" (split between two adjacent varying slots)
  567.     * are the vec3's.
  568.     */
  569.    enum packing_order_enum {
  570.       PACKING_ORDER_VEC4,
  571.       PACKING_ORDER_VEC2,
  572.       PACKING_ORDER_SCALAR,
  573.       PACKING_ORDER_VEC3,
  574.    };
  575.  
  576.    static unsigned compute_packing_class(ir_variable *var);
  577.    static packing_order_enum compute_packing_order(ir_variable *var);
  578.    static int match_comparator(const void *x_generic, const void *y_generic);
  579.  
  580.    /**
  581.     * Structure recording the relationship between a single producer output
  582.     * and a single consumer input.
  583.     */
  584.    struct match {
  585.       /**
  586.        * Packing class for this varying, computed by compute_packing_class().
  587.        */
  588.       unsigned packing_class;
  589.  
  590.       /**
  591.        * Packing order for this varying, computed by compute_packing_order().
  592.        */
  593.       packing_order_enum packing_order;
  594.       unsigned num_components;
  595.  
  596.       /**
  597.        * The output variable in the producer stage.
  598.        */
  599.       ir_variable *producer_var;
  600.  
  601.       /**
  602.        * The input variable in the consumer stage.
  603.        */
  604.       ir_variable *consumer_var;
  605.  
  606.       /**
  607.        * The location which has been assigned for this varying.  This is
  608.        * expressed in multiples of a float, with the first generic varying
  609.        * (i.e. the one referred to by VARYING_SLOT_VAR0) represented by the
  610.        * value 0.
  611.        */
  612.       unsigned generic_location;
  613.    } *matches;
  614.  
  615.    /**
  616.     * The number of elements in the \c matches array that are currently in
  617.     * use.
  618.     */
  619.    unsigned num_matches;
  620.  
  621.    /**
  622.     * The number of elements that were set aside for the \c matches array when
  623.     * it was allocated.
  624.     */
  625.    unsigned matches_capacity;
  626.  
  627.    const bool consumer_is_fs;
  628. };
  629.  
  630.  
  631. varying_matches::varying_matches(bool disable_varying_packing,
  632.                                  bool consumer_is_fs)
  633.    : disable_varying_packing(disable_varying_packing),
  634.      consumer_is_fs(consumer_is_fs)
  635. {
  636.    /* Note: this initial capacity is rather arbitrarily chosen to be large
  637.     * enough for many cases without wasting an unreasonable amount of space.
  638.     * varying_matches::record() will resize the array if there are more than
  639.     * this number of varyings.
  640.     */
  641.    this->matches_capacity = 8;
  642.    this->matches = (match *)
  643.       malloc(sizeof(*this->matches) * this->matches_capacity);
  644.    this->num_matches = 0;
  645. }
  646.  
  647.  
  648. varying_matches::~varying_matches()
  649. {
  650.    free(this->matches);
  651. }
  652.  
  653.  
  654. /**
  655.  * Record the given producer/consumer variable pair in the list of variables
  656.  * that should later be assigned locations.
  657.  *
  658.  * It is permissible for \c consumer_var to be NULL (this happens if a
  659.  * variable is output by the producer and consumed by transform feedback, but
  660.  * not consumed by the consumer).
  661.  *
  662.  * If \c producer_var has already been paired up with a consumer_var, or
  663.  * producer_var is part of fixed pipeline functionality (and hence already has
  664.  * a location assigned), this function has no effect.
  665.  *
  666.  * Note: as a side effect this function may change the interpolation type of
  667.  * \c producer_var, but only when the change couldn't possibly affect
  668.  * rendering.
  669.  */
  670. void
  671. varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
  672. {
  673.    if (!producer_var->is_unmatched_generic_inout) {
  674.       /* Either a location already exists for this variable (since it is part
  675.        * of fixed functionality), or it has already been recorded as part of a
  676.        * previous match.
  677.        */
  678.       return;
  679.    }
  680.  
  681.    if ((consumer_var == NULL && producer_var->type->contains_integer()) ||
  682.        !consumer_is_fs) {
  683.       /* Since this varying is not being consumed by the fragment shader, its
  684.        * interpolation type varying cannot possibly affect rendering.  Also,
  685.        * this variable is non-flat and is (or contains) an integer.
  686.        *
  687.        * lower_packed_varyings requires all integer varyings to flat,
  688.        * regardless of where they appear.  We can trivially satisfy that
  689.        * requirement by changing the interpolation type to flat here.
  690.        */
  691.       producer_var->centroid = false;
  692.       producer_var->interpolation = INTERP_QUALIFIER_FLAT;
  693.  
  694.       if (consumer_var) {
  695.          consumer_var->centroid = false;
  696.          consumer_var->interpolation = INTERP_QUALIFIER_FLAT;
  697.       }
  698.    }
  699.  
  700.    if (this->num_matches == this->matches_capacity) {
  701.       this->matches_capacity *= 2;
  702.       this->matches = (match *)
  703.          realloc(this->matches,
  704.                  sizeof(*this->matches) * this->matches_capacity);
  705.    }
  706.    this->matches[this->num_matches].packing_class
  707.       = this->compute_packing_class(producer_var);
  708.    this->matches[this->num_matches].packing_order
  709.       = this->compute_packing_order(producer_var);
  710.    if (this->disable_varying_packing) {
  711.       unsigned slots = producer_var->type->is_array()
  712.          ? (producer_var->type->length
  713.             * producer_var->type->fields.array->matrix_columns)
  714.          : producer_var->type->matrix_columns;
  715.       this->matches[this->num_matches].num_components = 4 * slots;
  716.    } else {
  717.       this->matches[this->num_matches].num_components
  718.          = producer_var->type->component_slots();
  719.    }
  720.    this->matches[this->num_matches].producer_var = producer_var;
  721.    this->matches[this->num_matches].consumer_var = consumer_var;
  722.    this->num_matches++;
  723.    producer_var->is_unmatched_generic_inout = 0;
  724.    if (consumer_var)
  725.       consumer_var->is_unmatched_generic_inout = 0;
  726. }
  727.  
  728.  
  729. /**
  730.  * Choose locations for all of the variable matches that were previously
  731.  * passed to varying_matches::record().
  732.  */
  733. unsigned
  734. varying_matches::assign_locations()
  735. {
  736.    /* Sort varying matches into an order that makes them easy to pack. */
  737.    qsort(this->matches, this->num_matches, sizeof(*this->matches),
  738.          &varying_matches::match_comparator);
  739.  
  740.    unsigned generic_location = 0;
  741.  
  742.    for (unsigned i = 0; i < this->num_matches; i++) {
  743.       /* Advance to the next slot if this varying has a different packing
  744.        * class than the previous one, and we're not already on a slot
  745.        * boundary.
  746.        */
  747.       if (i > 0 &&
  748.           this->matches[i - 1].packing_class
  749.           != this->matches[i].packing_class) {
  750.          generic_location = ALIGN(generic_location, 4);
  751.       }
  752.  
  753.       this->matches[i].generic_location = generic_location;
  754.  
  755.       generic_location += this->matches[i].num_components;
  756.    }
  757.  
  758.    return (generic_location + 3) / 4;
  759. }
  760.  
  761.  
  762. /**
  763.  * Update the producer and consumer shaders to reflect the locations
  764.  * assignments that were made by varying_matches::assign_locations().
  765.  */
  766. void
  767. varying_matches::store_locations(unsigned producer_base,
  768.                                  unsigned consumer_base) const
  769. {
  770.    for (unsigned i = 0; i < this->num_matches; i++) {
  771.       ir_variable *producer_var = this->matches[i].producer_var;
  772.       ir_variable *consumer_var = this->matches[i].consumer_var;
  773.       unsigned generic_location = this->matches[i].generic_location;
  774.       unsigned slot = generic_location / 4;
  775.       unsigned offset = generic_location % 4;
  776.  
  777.       producer_var->location = producer_base + slot;
  778.       producer_var->location_frac = offset;
  779.       if (consumer_var) {
  780.          assert(consumer_var->location == -1);
  781.          consumer_var->location = consumer_base + slot;
  782.          consumer_var->location_frac = offset;
  783.       }
  784.    }
  785. }
  786.  
  787.  
  788. /**
  789.  * Compute the "packing class" of the given varying.  This is an unsigned
  790.  * integer with the property that two variables in the same packing class can
  791.  * be safely backed into the same vec4.
  792.  */
  793. unsigned
  794. varying_matches::compute_packing_class(ir_variable *var)
  795. {
  796.    /* Without help from the back-end, there is no way to pack together
  797.     * variables with different interpolation types, because
  798.     * lower_packed_varyings must choose exactly one interpolation type for
  799.     * each packed varying it creates.
  800.     *
  801.     * However, we can safely pack together floats, ints, and uints, because:
  802.     *
  803.     * - varyings of base type "int" and "uint" must use the "flat"
  804.     *   interpolation type, which can only occur in GLSL 1.30 and above.
  805.     *
  806.     * - On platforms that support GLSL 1.30 and above, lower_packed_varyings
  807.     *   can store flat floats as ints without losing any information (using
  808.     *   the ir_unop_bitcast_* opcodes).
  809.     *
  810.     * Therefore, the packing class depends only on the interpolation type.
  811.     */
  812.    unsigned packing_class = var->centroid ? 1 : 0;
  813.    packing_class *= 4;
  814.    packing_class += var->interpolation;
  815.    return packing_class;
  816. }
  817.  
  818.  
  819. /**
  820.  * Compute the "packing order" of the given varying.  This is a sort key we
  821.  * use to determine when to attempt to pack the given varying relative to
  822.  * other varyings in the same packing class.
  823.  */
  824. varying_matches::packing_order_enum
  825. varying_matches::compute_packing_order(ir_variable *var)
  826. {
  827.    const glsl_type *element_type = var->type;
  828.  
  829.    while (element_type->base_type == GLSL_TYPE_ARRAY) {
  830.       element_type = element_type->fields.array;
  831.    }
  832.  
  833.    switch (element_type->component_slots() % 4) {
  834.    case 1: return PACKING_ORDER_SCALAR;
  835.    case 2: return PACKING_ORDER_VEC2;
  836.    case 3: return PACKING_ORDER_VEC3;
  837.    case 0: return PACKING_ORDER_VEC4;
  838.    default:
  839.       assert(!"Unexpected value of vector_elements");
  840.       return PACKING_ORDER_VEC4;
  841.    }
  842. }
  843.  
  844.  
  845. /**
  846.  * Comparison function passed to qsort() to sort varyings by packing_class and
  847.  * then by packing_order.
  848.  */
  849. int
  850. varying_matches::match_comparator(const void *x_generic, const void *y_generic)
  851. {
  852.    const match *x = (const match *) x_generic;
  853.    const match *y = (const match *) y_generic;
  854.  
  855.    if (x->packing_class != y->packing_class)
  856.       return x->packing_class - y->packing_class;
  857.    return x->packing_order - y->packing_order;
  858. }
  859.  
  860.  
  861. /**
  862.  * Is the given variable a varying variable to be counted against the
  863.  * limit in ctx->Const.MaxVarying?
  864.  * This includes variables such as texcoords, colors and generic
  865.  * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord.
  866.  */
  867. static bool
  868. is_varying_var(GLenum shaderType, const ir_variable *var)
  869. {
  870.    /* Only fragment shaders will take a varying variable as an input */
  871.    if (shaderType == GL_FRAGMENT_SHADER &&
  872.        var->mode == ir_var_shader_in) {
  873.       switch (var->location) {
  874.       case VARYING_SLOT_POS:
  875.       case VARYING_SLOT_FACE:
  876.       case VARYING_SLOT_PNTC:
  877.          return false;
  878.       default:
  879.          return true;
  880.       }
  881.    }
  882.    return false;
  883. }
  884.  
  885.  
  886. /**
  887.  * Visitor class that generates tfeedback_candidate structs describing all
  888.  * possible targets of transform feedback.
  889.  *
  890.  * tfeedback_candidate structs are stored in the hash table
  891.  * tfeedback_candidates, which is passed to the constructor.  This hash table
  892.  * maps varying names to instances of the tfeedback_candidate struct.
  893.  */
  894. class tfeedback_candidate_generator : public program_resource_visitor
  895. {
  896. public:
  897.    tfeedback_candidate_generator(void *mem_ctx,
  898.                                  hash_table *tfeedback_candidates)
  899.       : mem_ctx(mem_ctx),
  900.         tfeedback_candidates(tfeedback_candidates),
  901.         toplevel_var(NULL),
  902.         varying_floats(0)
  903.    {
  904.    }
  905.  
  906.    void process(ir_variable *var)
  907.    {
  908.       this->toplevel_var = var;
  909.       this->varying_floats = 0;
  910.       if (var->is_interface_instance())
  911.          program_resource_visitor::process(var->interface_type,
  912.                                            var->interface_type->name);
  913.       else
  914.          program_resource_visitor::process(var);
  915.    }
  916.  
  917. private:
  918.    virtual void visit_field(const glsl_type *type, const char *name,
  919.                             bool row_major)
  920.    {
  921.       assert(!type->is_record());
  922.       assert(!(type->is_array() && type->fields.array->is_record()));
  923.       assert(!type->is_interface());
  924.       assert(!(type->is_array() && type->fields.array->is_interface()));
  925.  
  926.       (void) row_major;
  927.  
  928.       tfeedback_candidate *candidate
  929.          = rzalloc(this->mem_ctx, tfeedback_candidate);
  930.       candidate->toplevel_var = this->toplevel_var;
  931.       candidate->type = type;
  932.       candidate->offset = this->varying_floats;
  933.       hash_table_insert(this->tfeedback_candidates, candidate,
  934.                         ralloc_strdup(this->mem_ctx, name));
  935.       this->varying_floats += type->component_slots();
  936.    }
  937.  
  938.    /**
  939.     * Memory context used to allocate hash table keys and values.
  940.     */
  941.    void * const mem_ctx;
  942.  
  943.    /**
  944.     * Hash table in which tfeedback_candidate objects should be stored.
  945.     */
  946.    hash_table * const tfeedback_candidates;
  947.  
  948.    /**
  949.     * Pointer to the toplevel variable that is being traversed.
  950.     */
  951.    ir_variable *toplevel_var;
  952.  
  953.    /**
  954.     * Total number of varying floats that have been visited so far.  This is
  955.     * used to determine the offset to each varying within the toplevel
  956.     * variable.
  957.     */
  958.    unsigned varying_floats;
  959. };
  960.  
  961.  
  962. /**
  963.  * Assign locations for all variables that are produced in one pipeline stage
  964.  * (the "producer") and consumed in the next stage (the "consumer").
  965.  *
  966.  * Variables produced by the producer may also be consumed by transform
  967.  * feedback.
  968.  *
  969.  * \param num_tfeedback_decls is the number of declarations indicating
  970.  *        variables that may be consumed by transform feedback.
  971.  *
  972.  * \param tfeedback_decls is a pointer to an array of tfeedback_decl objects
  973.  *        representing the result of parsing the strings passed to
  974.  *        glTransformFeedbackVaryings().  assign_location() will be called for
  975.  *        each of these objects that matches one of the outputs of the
  976.  *        producer.
  977.  *
  978.  * When num_tfeedback_decls is nonzero, it is permissible for the consumer to
  979.  * be NULL.  In this case, varying locations are assigned solely based on the
  980.  * requirements of transform feedback.
  981.  */
  982. bool
  983. assign_varying_locations(struct gl_context *ctx,
  984.                          void *mem_ctx,
  985.                          struct gl_shader_program *prog,
  986.                          gl_shader *producer, gl_shader *consumer,
  987.                          unsigned num_tfeedback_decls,
  988.                          tfeedback_decl *tfeedback_decls)
  989. {
  990.    const unsigned producer_base = VARYING_SLOT_VAR0;
  991.    const unsigned consumer_base = VARYING_SLOT_VAR0;
  992.    varying_matches matches(ctx->Const.DisableVaryingPacking,
  993.                            consumer && consumer->Type == GL_FRAGMENT_SHADER);
  994.    hash_table *tfeedback_candidates
  995.       = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
  996.    hash_table *consumer_inputs
  997.       = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
  998.    hash_table *consumer_interface_inputs
  999.       = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
  1000.  
  1001.    /* Operate in a total of three passes.
  1002.     *
  1003.     * 1. Assign locations for any matching inputs and outputs.
  1004.     *
  1005.     * 2. Mark output variables in the producer that do not have locations as
  1006.     *    not being outputs.  This lets the optimizer eliminate them.
  1007.     *
  1008.     * 3. Mark input variables in the consumer that do not have locations as
  1009.     *    not being inputs.  This lets the optimizer eliminate them.
  1010.     */
  1011.  
  1012.    if (consumer) {
  1013.       foreach_list(node, consumer->ir) {
  1014.          ir_variable *const input_var =
  1015.             ((ir_instruction *) node)->as_variable();
  1016.  
  1017.          if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) {
  1018.             if (input_var->interface_type != NULL) {
  1019.                char *const iface_field_name =
  1020.                   ralloc_asprintf(mem_ctx, "%s.%s",
  1021.                                   input_var->interface_type->name,
  1022.                                   input_var->name);
  1023.                hash_table_insert(consumer_interface_inputs, input_var,
  1024.                                  iface_field_name);
  1025.             } else {
  1026.                hash_table_insert(consumer_inputs, input_var,
  1027.                                  ralloc_strdup(mem_ctx, input_var->name));
  1028.             }
  1029.          }
  1030.       }
  1031.    }
  1032.  
  1033.    foreach_list(node, producer->ir) {
  1034.       ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
  1035.  
  1036.       if ((output_var == NULL) || (output_var->mode != ir_var_shader_out))
  1037.          continue;
  1038.  
  1039.       tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
  1040.       g.process(output_var);
  1041.  
  1042.       ir_variable *input_var;
  1043.       if (output_var->interface_type != NULL) {
  1044.          char *const iface_field_name =
  1045.             ralloc_asprintf(mem_ctx, "%s.%s",
  1046.                             output_var->interface_type->name,
  1047.                             output_var->name);
  1048.          input_var =
  1049.             (ir_variable *) hash_table_find(consumer_interface_inputs,
  1050.                                             iface_field_name);
  1051.       } else {
  1052.          input_var =
  1053.             (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
  1054.       }
  1055.  
  1056.       if (input_var && input_var->mode != ir_var_shader_in)
  1057.          input_var = NULL;
  1058.  
  1059.       if (input_var) {
  1060.          matches.record(output_var, input_var);
  1061.       }
  1062.    }
  1063.  
  1064.    for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
  1065.       if (!tfeedback_decls[i].is_varying())
  1066.          continue;
  1067.  
  1068.       const tfeedback_candidate *matched_candidate
  1069.          = tfeedback_decls[i].find_candidate(prog, tfeedback_candidates);
  1070.  
  1071.       if (matched_candidate == NULL) {
  1072.          hash_table_dtor(tfeedback_candidates);
  1073.          hash_table_dtor(consumer_inputs);
  1074.          hash_table_dtor(consumer_interface_inputs);
  1075.          return false;
  1076.       }
  1077.  
  1078.       if (matched_candidate->toplevel_var->is_unmatched_generic_inout)
  1079.          matches.record(matched_candidate->toplevel_var, NULL);
  1080.    }
  1081.  
  1082.    const unsigned slots_used = matches.assign_locations();
  1083.    matches.store_locations(producer_base, consumer_base);
  1084.  
  1085.    for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
  1086.       if (!tfeedback_decls[i].is_varying())
  1087.          continue;
  1088.  
  1089.       if (!tfeedback_decls[i].assign_location(ctx, prog)) {
  1090.          hash_table_dtor(tfeedback_candidates);
  1091.          hash_table_dtor(consumer_inputs);
  1092.          hash_table_dtor(consumer_interface_inputs);
  1093.          return false;
  1094.       }
  1095.    }
  1096.  
  1097.    hash_table_dtor(tfeedback_candidates);
  1098.    hash_table_dtor(consumer_inputs);
  1099.    hash_table_dtor(consumer_interface_inputs);
  1100.  
  1101.    if (ctx->Const.DisableVaryingPacking) {
  1102.       /* Transform feedback code assumes varyings are packed, so if the driver
  1103.        * has disabled varying packing, make sure it does not support transform
  1104.        * feedback.
  1105.        */
  1106.       assert(!ctx->Extensions.EXT_transform_feedback);
  1107.    } else {
  1108.       lower_packed_varyings(mem_ctx, producer_base, slots_used,
  1109.                             ir_var_shader_out, producer);
  1110.       if (consumer) {
  1111.          lower_packed_varyings(mem_ctx, consumer_base, slots_used,
  1112.                                ir_var_shader_in, consumer);
  1113.       }
  1114.    }
  1115.  
  1116.    if (consumer) {
  1117.       foreach_list(node, consumer->ir) {
  1118.          ir_variable *const var = ((ir_instruction *) node)->as_variable();
  1119.  
  1120.          if (var && var->mode == ir_var_shader_in &&
  1121.              var->is_unmatched_generic_inout) {
  1122.             if (prog->Version <= 120) {
  1123.                /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
  1124.                 *
  1125.                 *     Only those varying variables used (i.e. read) in
  1126.                 *     the fragment shader executable must be written to
  1127.                 *     by the vertex shader executable; declaring
  1128.                 *     superfluous varying variables in a vertex shader is
  1129.                 *     permissible.
  1130.                 *
  1131.                 * We interpret this text as meaning that the VS must
  1132.                 * write the variable for the FS to read it.  See
  1133.                 * "glsl1-varying read but not written" in piglit.
  1134.                 */
  1135.  
  1136.                linker_error(prog, "%s shader varying %s not written "
  1137.                             "by %s shader\n.",
  1138.                             _mesa_glsl_shader_target_name(consumer->Type),
  1139.                             var->name,
  1140.                             _mesa_glsl_shader_target_name(producer->Type));
  1141.             }
  1142.  
  1143.             /* An 'in' variable is only really a shader input if its
  1144.              * value is written by the previous stage.
  1145.              */
  1146.             var->mode = ir_var_auto;
  1147.          }
  1148.       }
  1149.    }
  1150.  
  1151.    return true;
  1152. }
  1153.  
  1154. bool
  1155. check_against_varying_limit(struct gl_context *ctx,
  1156.                             struct gl_shader_program *prog,
  1157.                             gl_shader *consumer)
  1158. {
  1159.    unsigned varying_vectors = 0;
  1160.  
  1161.    foreach_list(node, consumer->ir) {
  1162.       ir_variable *const var = ((ir_instruction *) node)->as_variable();
  1163.  
  1164.       if (var && var->mode == ir_var_shader_in &&
  1165.           is_varying_var(consumer->Type, var)) {
  1166.          /* The packing rules used for vertex shader inputs are also
  1167.           * used for fragment shader inputs.
  1168.           */
  1169.          varying_vectors += count_attribute_slots(var->type);
  1170.       }
  1171.    }
  1172.  
  1173.    if (ctx->API == API_OPENGLES2 || prog->IsES) {
  1174.       if (varying_vectors > ctx->Const.MaxVarying) {
  1175.          linker_error(prog, "shader uses too many varying vectors "
  1176.                       "(%u > %u)\n",
  1177.                       varying_vectors, ctx->Const.MaxVarying);
  1178.          return false;
  1179.       }
  1180.    } else {
  1181.       const unsigned float_components = varying_vectors * 4;
  1182.       if (float_components > ctx->Const.MaxVarying * 4) {
  1183.          linker_error(prog, "shader uses too many varying components "
  1184.                       "(%u > %u)\n",
  1185.                       float_components, ctx->Const.MaxVarying * 4);
  1186.          return false;
  1187.       }
  1188.    }
  1189.  
  1190.    return true;
  1191. }
  1192.