Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. #include "link_uniform_block_active_visitor.h"
  25. #include "program.h"
  26.  
  27. link_uniform_block_active *
  28. process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
  29. {
  30.    const hash_entry *const existing_block =
  31.       _mesa_hash_table_search(ht, var->get_interface_type()->name);
  32.  
  33.    const glsl_type *const block_type = var->is_interface_instance()
  34.       ? var->type : var->get_interface_type();
  35.  
  36.  
  37.    /* If a block with this block-name has not previously been seen, add it.
  38.     * If a block with this block-name has been seen, it must be identical to
  39.     * the block currently being examined.
  40.     */
  41.    if (existing_block == NULL) {
  42.       link_uniform_block_active *const b =
  43.          rzalloc(mem_ctx, struct link_uniform_block_active);
  44.  
  45.       b->type = block_type;
  46.       b->has_instance_name = var->is_interface_instance();
  47.  
  48.       if (var->data.explicit_binding) {
  49.          b->has_binding = true;
  50.          b->binding = var->data.binding;
  51.       } else {
  52.          b->has_binding = false;
  53.          b->binding = 0;
  54.       }
  55.  
  56.       _mesa_hash_table_insert(ht, var->get_interface_type()->name, (void *) b);
  57.       return b;
  58.    } else {
  59.       link_uniform_block_active *const b =
  60.          (link_uniform_block_active *) existing_block->data;
  61.  
  62.       if (b->type != block_type
  63.           || b->has_instance_name != var->is_interface_instance())
  64.          return NULL;
  65.       else
  66.          return b;
  67.    }
  68.  
  69.    assert(!"Should not get here.");
  70.    return NULL;
  71. }
  72.  
  73. ir_visitor_status
  74. link_uniform_block_active_visitor::visit(ir_variable *var)
  75. {
  76.    if (!var->is_in_uniform_block())
  77.       return visit_continue;
  78.  
  79.    const glsl_type *const block_type = var->is_interface_instance()
  80.       ? var->type : var->get_interface_type();
  81.  
  82.    /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says:
  83.     *
  84.     *     "All members of a named uniform block declared with a shared or
  85.     *     std140 layout qualifier are considered active, even if they are not
  86.     *     referenced in any shader in the program. The uniform block itself is
  87.     *     also considered active, even if no member of the block is
  88.     *     referenced."
  89.     */
  90.    if (block_type->interface_packing == GLSL_INTERFACE_PACKING_PACKED)
  91.       return visit_continue;
  92.  
  93.    /* Process the block.  Bail if there was an error.
  94.     */
  95.    link_uniform_block_active *const b =
  96.       process_block(this->mem_ctx, this->ht, var);
  97.    if (b == NULL) {
  98.       linker_error(this->prog,
  99.                    "uniform block `%s' has mismatching definitions",
  100.                    var->get_interface_type()->name);
  101.       this->success = false;
  102.       return visit_stop;
  103.    }
  104.  
  105.    assert(b->num_array_elements == 0);
  106.    assert(b->array_elements == NULL);
  107.    assert(b->type != NULL);
  108.  
  109.    return visit_continue;
  110. }
  111.  
  112. ir_visitor_status
  113. link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
  114. {
  115.    ir_dereference_variable *const d = ir->array->as_dereference_variable();
  116.    ir_variable *const var = (d == NULL) ? NULL : d->var;
  117.  
  118.    /* If the r-value being dereferenced is not a variable (e.g., a field of a
  119.     * structure) or is not a uniform block instance, continue.
  120.     *
  121.     * WARNING: It is not enough for the variable to be part of uniform block.
  122.     * It must represent the entire block.  Arrays (or matrices) inside blocks
  123.     * that lack an instance name are handled by the ir_dereference_variable
  124.     * function.
  125.     */
  126.    if (var == NULL
  127.        || !var->is_in_uniform_block()
  128.        || !var->is_interface_instance())
  129.       return visit_continue;
  130.  
  131.    /* Process the block.  Bail if there was an error.
  132.     */
  133.    link_uniform_block_active *const b =
  134.       process_block(this->mem_ctx, this->ht, var);
  135.    if (b == NULL) {
  136.       linker_error(prog,
  137.                    "uniform block `%s' has mismatching definitions",
  138.                    var->get_interface_type()->name);
  139.       this->success = false;
  140.       return visit_stop;
  141.    }
  142.  
  143.    /* Block arrays must be declared with an instance name.
  144.     */
  145.    assert(b->has_instance_name);
  146.    assert((b->num_array_elements == 0) == (b->array_elements == NULL));
  147.    assert(b->type != NULL);
  148.  
  149.    ir_constant *c = ir->array_index->as_constant();
  150.  
  151.    if (c) {
  152.       /* Index is a constant, so mark just that element used, if not already */
  153.       const unsigned idx = c->get_uint_component(0);
  154.  
  155.       unsigned i;
  156.       for (i = 0; i < b->num_array_elements; i++) {
  157.          if (b->array_elements[i] == idx)
  158.             break;
  159.       }
  160.  
  161.       assert(i <= b->num_array_elements);
  162.  
  163.       if (i == b->num_array_elements) {
  164.          b->array_elements = reralloc(this->mem_ctx,
  165.                                       b->array_elements,
  166.                                       unsigned,
  167.                                       b->num_array_elements + 1);
  168.  
  169.          b->array_elements[b->num_array_elements] = idx;
  170.  
  171.          b->num_array_elements++;
  172.       }
  173.    } else {
  174.       /* The array index is not a constant, so mark the entire array used. */
  175.       assert(b->type->is_array());
  176.       if (b->num_array_elements < b->type->length) {
  177.          b->num_array_elements = b->type->length;
  178.          b->array_elements = reralloc(this->mem_ctx,
  179.                                       b->array_elements,
  180.                                       unsigned,
  181.                                       b->num_array_elements);
  182.  
  183.          for (unsigned i = 0; i < b->num_array_elements; i++) {
  184.             b->array_elements[i] = i;
  185.          }
  186.       }
  187.    }
  188.  
  189.    return visit_continue_with_parent;
  190. }
  191.  
  192. ir_visitor_status
  193. link_uniform_block_active_visitor::visit(ir_dereference_variable *ir)
  194. {
  195.    ir_variable *var = ir->var;
  196.  
  197.    if (!var->is_in_uniform_block())
  198.       return visit_continue;
  199.  
  200.    assert(!var->is_interface_instance() || !var->type->is_array());
  201.  
  202.    /* Process the block.  Bail if there was an error.
  203.     */
  204.    link_uniform_block_active *const b =
  205.       process_block(this->mem_ctx, this->ht, var);
  206.    if (b == NULL) {
  207.       linker_error(this->prog,
  208.                    "uniform block `%s' has mismatching definitions",
  209.                    var->get_interface_type()->name);
  210.       this->success = false;
  211.       return visit_stop;
  212.    }
  213.  
  214.    assert(b->num_array_elements == 0);
  215.    assert(b->array_elements == NULL);
  216.    assert(b->type != NULL);
  217.  
  218.    return visit_continue;
  219. }
  220.