Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2013 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_interface_blocks.cpp
  26.  * Linker support for GLSL's interface blocks.
  27.  */
  28.  
  29. #include "ir.h"
  30. #include "glsl_symbol_table.h"
  31. #include "linker.h"
  32. #include "main/macros.h"
  33. #include "program/hash_table.h"
  34.  
  35.  
  36. namespace {
  37.  
  38. /**
  39.  * Information about a single interface block definition that we need to keep
  40.  * track of in order to check linkage rules.
  41.  *
  42.  * Note: this class is expected to be short lived, so it doesn't make copies
  43.  * of the strings it references; it simply borrows the pointers from the
  44.  * ir_variable class.
  45.  */
  46. struct interface_block_definition
  47. {
  48.    /**
  49.     * Extract an interface block definition from an ir_variable that
  50.     * represents either the interface instance (for named interfaces), or a
  51.     * member of the interface (for unnamed interfaces).
  52.     */
  53.    explicit interface_block_definition(ir_variable *var)
  54.       : var(var),
  55.         type(var->get_interface_type()),
  56.         instance_name(NULL)
  57.    {
  58.       if (var->is_interface_instance()) {
  59.          instance_name = var->name;
  60.       }
  61.       explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly);
  62.    }
  63.    /**
  64.     * Interface block ir_variable
  65.     */
  66.    ir_variable *var;
  67.  
  68.    /**
  69.     * Interface block type
  70.     */
  71.    const glsl_type *type;
  72.  
  73.    /**
  74.     * For a named interface block, the instance name.  Otherwise NULL.
  75.     */
  76.    const char *instance_name;
  77.  
  78.    /**
  79.     * True if this interface block was explicitly declared in the shader;
  80.     * false if it was an implicitly declared built-in interface block.
  81.     */
  82.    bool explicitly_declared;
  83. };
  84.  
  85.  
  86. /**
  87.  * Check if two interfaces match, according to intrastage interface matching
  88.  * rules.  If they do, and the first interface uses an unsized array, it will
  89.  * be updated to reflect the array size declared in the second interface.
  90.  */
  91. bool
  92. intrastage_match(interface_block_definition *a,
  93.                  const interface_block_definition *b,
  94.                  ir_variable_mode mode,
  95.                  struct gl_shader_program *prog)
  96. {
  97.    /* Types must match. */
  98.    if (a->type != b->type) {
  99.       /* Exception: if both the interface blocks are implicitly declared,
  100.        * don't force their types to match.  They might mismatch due to the two
  101.        * shaders using different GLSL versions, and that's ok.
  102.        */
  103.       if (a->explicitly_declared || b->explicitly_declared)
  104.          return false;
  105.    }
  106.  
  107.    /* Presence/absence of interface names must match. */
  108.    if ((a->instance_name == NULL) != (b->instance_name == NULL))
  109.       return false;
  110.  
  111.    /* For uniforms, instance names need not match.  For shader ins/outs,
  112.     * it's not clear from the spec whether they need to match, but
  113.     * Mesa's implementation relies on them matching.
  114.     */
  115.    if (a->instance_name != NULL && mode != ir_var_uniform &&
  116.        strcmp(a->instance_name, b->instance_name) != 0) {
  117.       return false;
  118.    }
  119.  
  120.    /* If a block is an array then it must match across the shader.
  121.     * Unsized arrays are also processed and matched agaist sized arrays.
  122.     */
  123.    if (b->var->type != a->var->type &&
  124.        (b->instance_name != NULL || a->instance_name != NULL) &&
  125.        !validate_intrastage_arrays(prog, b->var, a->var))
  126.       return false;
  127.  
  128.    return true;
  129. }
  130.  
  131.  
  132. /**
  133.  * Check if two interfaces match, according to interstage (in/out) interface
  134.  * matching rules.
  135.  *
  136.  * If \c extra_array_level is true, then vertex-to-geometry shader matching
  137.  * rules are enforced (i.e. a successful match requires the consumer interface
  138.  * to be an array and the producer interface to be a non-array).
  139.  */
  140. bool
  141. interstage_match(const interface_block_definition *producer,
  142.                  const interface_block_definition *consumer,
  143.                  bool extra_array_level)
  144. {
  145.    /* Unsized arrays should not occur during interstage linking.  They
  146.     * should have all been assigned a size by link_intrastage_shaders.
  147.     */
  148.    assert(!consumer->var->type->is_unsized_array());
  149.    assert(!producer->var->type->is_unsized_array());
  150.  
  151.    /* Types must match. */
  152.    if (consumer->type != producer->type) {
  153.       /* Exception: if both the interface blocks are implicitly declared,
  154.        * don't force their types to match.  They might mismatch due to the two
  155.        * shaders using different GLSL versions, and that's ok.
  156.        */
  157.       if (consumer->explicitly_declared || producer->explicitly_declared)
  158.          return false;
  159.    }
  160.  
  161.    /* Ignore outermost array if geom shader */
  162.    const glsl_type *consumer_instance_type;
  163.    if (extra_array_level) {
  164.       consumer_instance_type = consumer->var->type->fields.array;
  165.    } else {
  166.       consumer_instance_type = consumer->var->type;
  167.    }
  168.  
  169.    /* If a block is an array then it must match across shaders.
  170.     * Since unsized arrays have been ruled out, we can check this by just
  171.     * making sure the types are equal.
  172.     */
  173.    if ((consumer->instance_name != NULL &&
  174.         consumer_instance_type->is_array()) ||
  175.        (producer->instance_name != NULL &&
  176.         producer->var->type->is_array())) {
  177.       if (consumer_instance_type != producer->var->type)
  178.          return false;
  179.    }
  180.  
  181.    return true;
  182. }
  183.  
  184.  
  185. /**
  186.  * This class keeps track of a mapping from an interface block name to the
  187.  * necessary information about that interface block to determine whether to
  188.  * generate a link error.
  189.  *
  190.  * Note: this class is expected to be short lived, so it doesn't make copies
  191.  * of the strings it references; it simply borrows the pointers from the
  192.  * ir_variable class.
  193.  */
  194. class interface_block_definitions
  195. {
  196. public:
  197.    interface_block_definitions()
  198.       : mem_ctx(ralloc_context(NULL)),
  199.         ht(hash_table_ctor(0, hash_table_string_hash,
  200.                            hash_table_string_compare))
  201.    {
  202.    }
  203.  
  204.    ~interface_block_definitions()
  205.    {
  206.       hash_table_dtor(ht);
  207.       ralloc_free(mem_ctx);
  208.    }
  209.  
  210.    /**
  211.     * Lookup the interface definition having the given block name.  Return
  212.     * NULL if none is found.
  213.     */
  214.    interface_block_definition *lookup(const char *block_name)
  215.    {
  216.       return (interface_block_definition *) hash_table_find(ht, block_name);
  217.    }
  218.  
  219.    /**
  220.     * Add a new interface definition.
  221.     */
  222.    void store(const interface_block_definition &def)
  223.    {
  224.       interface_block_definition *hash_entry =
  225.          rzalloc(mem_ctx, interface_block_definition);
  226.       *hash_entry = def;
  227.       hash_table_insert(ht, hash_entry, def.type->name);
  228.    }
  229.  
  230. private:
  231.    /**
  232.     * Ralloc context for data structures allocated by this class.
  233.     */
  234.    void *mem_ctx;
  235.  
  236.    /**
  237.     * Hash table mapping interface block name to an \c
  238.     * interface_block_definition struct.  interface_block_definition structs
  239.     * are allocated using \c mem_ctx.
  240.     */
  241.    hash_table *ht;
  242. };
  243.  
  244.  
  245. }; /* anonymous namespace */
  246.  
  247.  
  248. void
  249. validate_intrastage_interface_blocks(struct gl_shader_program *prog,
  250.                                      const gl_shader **shader_list,
  251.                                      unsigned num_shaders)
  252. {
  253.    interface_block_definitions in_interfaces;
  254.    interface_block_definitions out_interfaces;
  255.    interface_block_definitions uniform_interfaces;
  256.  
  257.    for (unsigned int i = 0; i < num_shaders; i++) {
  258.       if (shader_list[i] == NULL)
  259.          continue;
  260.  
  261.       foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
  262.          ir_variable *var = node->as_variable();
  263.          if (!var)
  264.             continue;
  265.  
  266.          const glsl_type *iface_type = var->get_interface_type();
  267.  
  268.          if (iface_type == NULL)
  269.             continue;
  270.  
  271.          interface_block_definitions *definitions;
  272.          switch (var->data.mode) {
  273.          case ir_var_shader_in:
  274.             definitions = &in_interfaces;
  275.             break;
  276.          case ir_var_shader_out:
  277.             definitions = &out_interfaces;
  278.             break;
  279.          case ir_var_uniform:
  280.             definitions = &uniform_interfaces;
  281.             break;
  282.          default:
  283.             /* Only in, out, and uniform interfaces are legal, so we should
  284.              * never get here.
  285.              */
  286.             assert(!"illegal interface type");
  287.             continue;
  288.          }
  289.  
  290.          const interface_block_definition def(var);
  291.          interface_block_definition *prev_def =
  292.             definitions->lookup(iface_type->name);
  293.  
  294.          if (prev_def == NULL) {
  295.             /* This is the first time we've seen the interface, so save
  296.              * it into the appropriate data structure.
  297.              */
  298.             definitions->store(def);
  299.          } else if (!intrastage_match(prev_def, &def,
  300.                                       (ir_variable_mode) var->data.mode,
  301.                                       prog)) {
  302.             linker_error(prog, "definitions of interface block `%s' do not"
  303.                          " match\n", iface_type->name);
  304.             return;
  305.          }
  306.       }
  307.    }
  308. }
  309.  
  310. void
  311. validate_interstage_inout_blocks(struct gl_shader_program *prog,
  312.                                  const gl_shader *producer,
  313.                                  const gl_shader *consumer)
  314. {
  315.    interface_block_definitions definitions;
  316.    const bool extra_array_level = consumer->Stage == MESA_SHADER_GEOMETRY;
  317.  
  318.    /* Add input interfaces from the consumer to the symbol table. */
  319.    foreach_in_list(ir_instruction, node, consumer->ir) {
  320.       ir_variable *var = node->as_variable();
  321.       if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in)
  322.          continue;
  323.  
  324.       definitions.store(interface_block_definition(var));
  325.    }
  326.  
  327.    /* Verify that the producer's output interfaces match. */
  328.    foreach_in_list(ir_instruction, node, producer->ir) {
  329.       ir_variable *var = node->as_variable();
  330.       if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out)
  331.          continue;
  332.  
  333.       interface_block_definition *consumer_def =
  334.          definitions.lookup(var->get_interface_type()->name);
  335.  
  336.       /* The consumer doesn't use this output block.  Ignore it. */
  337.       if (consumer_def == NULL)
  338.          continue;
  339.  
  340.       const interface_block_definition producer_def(var);
  341.  
  342.       if (!interstage_match(&producer_def, consumer_def, extra_array_level)) {
  343.          linker_error(prog, "definitions of interface block `%s' do not "
  344.                       "match\n", var->get_interface_type()->name);
  345.          return;
  346.       }
  347.    }
  348. }
  349.  
  350.  
  351. void
  352. validate_interstage_uniform_blocks(struct gl_shader_program *prog,
  353.                                    gl_shader **stages, int num_stages)
  354. {
  355.    interface_block_definitions definitions;
  356.  
  357.    for (int i = 0; i < num_stages; i++) {
  358.       if (stages[i] == NULL)
  359.          continue;
  360.  
  361.       const gl_shader *stage = stages[i];
  362.       foreach_in_list(ir_instruction, node, stage->ir) {
  363.          ir_variable *var = node->as_variable();
  364.          if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform)
  365.             continue;
  366.  
  367.          interface_block_definition *old_def =
  368.             definitions.lookup(var->get_interface_type()->name);
  369.          const interface_block_definition new_def(var);
  370.          if (old_def == NULL) {
  371.             definitions.store(new_def);
  372.          } else {
  373.             /* Interstage uniform matching rules are the same as intrastage
  374.              * uniform matchin rules (for uniforms, it is as though all
  375.              * shaders are in the same shader stage).
  376.              */
  377.             if (!intrastage_match(old_def, &new_def, ir_var_uniform, prog)) {
  378.                linker_error(prog, "definitions of interface block `%s' do not "
  379.                             "match\n", var->get_interface_type()->name);
  380.                return;
  381.             }
  382.          }
  383.       }
  384.    }
  385. }
  386.