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 uint32_t h = _mesa_hash_string(var->interface_type->name);
  31.    const hash_entry *const existing_block =
  32.       _mesa_hash_table_search(ht, h, var->interface_type->name);
  33.  
  34.    const glsl_type *const block_type = var->is_interface_instance()
  35.       ? var->type : var->interface_type;
  36.  
  37.  
  38.    /* If a block with this block-name has not previously been seen, add it.
  39.     * If a block with this block-name has been seen, it must be identical to
  40.     * the block currently being examined.
  41.     */
  42.    if (existing_block == NULL) {
  43.       link_uniform_block_active *const b =
  44.          rzalloc(mem_ctx, struct link_uniform_block_active);
  45.  
  46.       b->type = block_type;
  47.       b->has_instance_name = var->is_interface_instance();
  48.  
  49.       _mesa_hash_table_insert(ht, h, var->interface_type->name,
  50.                               (void *) b);
  51.       return b;
  52.    } else {
  53.       link_uniform_block_active *const b =
  54.          (link_uniform_block_active *) existing_block->data;
  55.  
  56.       if (b->type != block_type
  57.           || b->has_instance_name != var->is_interface_instance())
  58.          return NULL;
  59.       else
  60.          return b;
  61.    }
  62.  
  63.    assert(!"Should not get here.");
  64.    return NULL;
  65. }
  66.  
  67. ir_visitor_status
  68. link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
  69. {
  70.    ir_dereference_variable *const d = ir->array->as_dereference_variable();
  71.    ir_variable *const var = (d == NULL) ? NULL : d->var;
  72.  
  73.    /* If the r-value being dereferenced is not a variable (e.g., a field of a
  74.     * structure) or is not a uniform block instance, continue.
  75.     *
  76.     * WARNING: It is not enough for the variable to be part of uniform block.
  77.     * It must represent the entire block.  Arrays (or matrices) inside blocks
  78.     * that lack an instance name are handled by the ir_dereference_variable
  79.     * function.
  80.     */
  81.    if (var == NULL
  82.        || !var->is_in_uniform_block()
  83.        || !var->is_interface_instance())
  84.       return visit_continue;
  85.  
  86.    /* Process the block.  Bail if there was an error.
  87.     */
  88.    link_uniform_block_active *const b =
  89.       process_block(this->mem_ctx, this->ht, var);
  90.    if (b == NULL) {
  91.       linker_error(prog,
  92.                    "uniform block `%s' has mismatching definitions",
  93.                    var->interface_type->name);
  94.       this->success = false;
  95.       return visit_stop;
  96.    }
  97.  
  98.    /* Block arrays must be declared with an instance name.
  99.     */
  100.    assert(b->has_instance_name);
  101.    assert((b->num_array_elements == 0) == (b->array_elements == NULL));
  102.    assert(b->type != NULL);
  103.  
  104.    /* Determine whether or not this array index has already been added to the
  105.     * list of active array indices.  At this point all constant folding must
  106.     * have occured, and the array index must be a constant.
  107.     */
  108.    ir_constant *c = ir->array_index->as_constant();
  109.    assert(c != NULL);
  110.  
  111.    const unsigned idx = c->get_uint_component(0);
  112.  
  113.    unsigned i;
  114.    for (i = 0; i < b->num_array_elements; i++) {
  115.       if (b->array_elements[i] == idx)
  116.          break;
  117.    }
  118.  
  119.    assert(i <= b->num_array_elements);
  120.  
  121.    if (i == b->num_array_elements) {
  122.       b->array_elements = reralloc(this->mem_ctx,
  123.                                    b->array_elements,
  124.                                    unsigned,
  125.                                    b->num_array_elements + 1);
  126.  
  127.       b->array_elements[b->num_array_elements] = idx;
  128.  
  129.       b->num_array_elements++;
  130.    }
  131.  
  132.    return visit_continue_with_parent;
  133. }
  134.  
  135. ir_visitor_status
  136. link_uniform_block_active_visitor::visit(ir_dereference_variable *ir)
  137. {
  138.    ir_variable *var = ir->var;
  139.  
  140.    if (!var->is_in_uniform_block())
  141.       return visit_continue;
  142.  
  143.    assert(!var->is_interface_instance() || !var->type->is_array());
  144.  
  145.    /* Process the block.  Bail if there was an error.
  146.     */
  147.    link_uniform_block_active *const b =
  148.       process_block(this->mem_ctx, this->ht, var);
  149.    if (b == NULL) {
  150.       linker_error(this->prog,
  151.                    "uniform block `%s' has mismatching definitions",
  152.                    var->interface_type->name);
  153.       this->success = false;
  154.       return visit_stop;
  155.    }
  156.  
  157.    assert(b->num_array_elements == 0);
  158.    assert(b->array_elements == NULL);
  159.    assert(b->type != NULL);
  160.  
  161.    return visit_continue;
  162. }
  163.