Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2010 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 ir_set_program_inouts.cpp
  26.  *
  27.  * Sets the InputsRead and OutputsWritten of Mesa programs.
  28.  *
  29.  * Mesa programs (gl_program, not gl_shader_program) have a set of
  30.  * flags indicating which varyings are read and written.  Computing
  31.  * which are actually read from some sort of backend code can be
  32.  * tricky when variable array indexing involved.  So this pass
  33.  * provides support for setting InputsRead and OutputsWritten right
  34.  * from the GLSL IR.
  35.  */
  36.  
  37. extern "C" {
  38. #include "main/core.h" /* for struct gl_program */
  39. #include "program/hash_table.h"
  40. }
  41. #include "ir.h"
  42. #include "ir_visitor.h"
  43. #include "glsl_types.h"
  44.  
  45. class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
  46. public:
  47.    ir_set_program_inouts_visitor(struct gl_program *prog)
  48.    {
  49.       this->prog = prog;
  50.       this->ht = hash_table_ctor(0,
  51.                                  hash_table_pointer_hash,
  52.                                  hash_table_pointer_compare);
  53.    }
  54.    ~ir_set_program_inouts_visitor()
  55.    {
  56.       hash_table_dtor(this->ht);
  57.    }
  58.  
  59.    virtual ir_visitor_status visit_enter(ir_dereference_array *);
  60.    virtual ir_visitor_status visit_enter(ir_function_signature *);
  61.    virtual ir_visitor_status visit(ir_dereference_variable *);
  62.    virtual ir_visitor_status visit(ir_variable *);
  63.  
  64.    struct gl_program *prog;
  65.    struct hash_table *ht;
  66. };
  67.  
  68. static void
  69. mark(struct gl_program *prog, ir_variable *var, int offset, int len)
  70. {
  71.    /* As of GLSL 1.20, varyings can only be floats, floating-point
  72.     * vectors or matrices, or arrays of them.  For Mesa programs using
  73.     * InputsRead/OutputsWritten, everything but matrices uses one
  74.     * slot, while matrices use a slot per column.  Presumably
  75.     * something doing a more clever packing would use something other
  76.     * than InputsRead/OutputsWritten.
  77.     */
  78.  
  79.    for (int i = 0; i < len; i++) {
  80.       if (var->mode == ir_var_in)
  81.          prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i);
  82.       else
  83.          prog->OutputsWritten |= BITFIELD64_BIT(var->location + offset + i);
  84.    }
  85. }
  86.  
  87. /* Default handler: Mark all the locations in the variable as used. */
  88. ir_visitor_status
  89. ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
  90. {
  91.    if (hash_table_find(this->ht, ir->var) == NULL)
  92.       return visit_continue;
  93.  
  94.    if (ir->type->is_array()) {
  95.       for (unsigned int i = 0; i < ir->type->length; i++) {
  96.          mark(this->prog, ir->var, i,
  97.               ir->type->length * ir->type->fields.array->matrix_columns);
  98.       }
  99.    } else {
  100.       mark(this->prog, ir->var, 0, ir->type->matrix_columns);
  101.    }
  102.  
  103.    return visit_continue;
  104. }
  105.  
  106. ir_visitor_status
  107. ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
  108. {
  109.    ir_dereference_variable *deref_var;
  110.    ir_constant *index = ir->array_index->as_constant();
  111.    deref_var = ir->array->as_dereference_variable();
  112.    ir_variable *var = NULL;
  113.  
  114.    /* Check that we're dereferencing a shader in or out */
  115.    if (deref_var)
  116.       var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
  117.  
  118.    if (index && var) {
  119.       int width = 1;
  120.  
  121.       if (deref_var->type->is_array() &&
  122.           deref_var->type->fields.array->is_matrix()) {
  123.          width = deref_var->type->fields.array->matrix_columns;
  124.       }
  125.  
  126.       mark(this->prog, var, index->value.i[0] * width, width);
  127.       return visit_continue_with_parent;
  128.    }
  129.  
  130.    return visit_continue;
  131. }
  132.  
  133. ir_visitor_status
  134. ir_set_program_inouts_visitor::visit(ir_variable *ir)
  135. {
  136.    if (ir->mode == ir_var_in ||
  137.        ir->mode == ir_var_out) {
  138.       hash_table_insert(this->ht, ir, ir);
  139.    }
  140.  
  141.    return visit_continue;
  142. }
  143.  
  144. ir_visitor_status
  145. ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
  146. {
  147.    /* We don't want to descend into the function parameters and
  148.     * consider them as shader inputs or outputs.
  149.     */
  150.    visit_list_elements(this, &ir->body);
  151.    return visit_continue_with_parent;
  152. }
  153.  
  154. void
  155. do_set_program_inouts(exec_list *instructions, struct gl_program *prog)
  156. {
  157.    ir_set_program_inouts_visitor v(prog);
  158.  
  159.    prog->InputsRead = 0;
  160.    prog->OutputsWritten = 0;
  161.    visit_list_elements(&v, instructions);
  162. }
  163.