glsl/types: add new subroutine type (v3.2)
authorDave Airlie <airlied@redhat.com>
Mon, 20 Apr 2015 00:16:55 +0000 (10:16 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 23 Jul 2015 07:25:25 +0000 (17:25 +1000)
This type will be used to store the name of subroutine types

as in subroutine void myfunc(void);
will store myfunc into a subroutine type.

This is required to the parser can identify a subroutine
type in a uniform decleration as a valid type, and also for
looking up the type later.

Also add contains_subroutine method.

v2: handle subroutine to int comparisons, needed
for lowering pass.
v3: do subroutine to int with it's own IR
operation to avoid hacking on asserts (Kayden)
v3.1: fix warnings in this patch, fix nir,
fix tgsi
v3.2: fixup tests

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
Signed-off-by: Dave Airlie <airlied@redhat.com>
tests: fix warnings

13 files changed:
src/glsl/ast_to_hir.cpp
src/glsl/glsl_types.cpp
src/glsl/glsl_types.h
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_builder.cpp
src/glsl/ir_builder.h
src/glsl/ir_clone.cpp
src/glsl/ir_validate.cpp
src/glsl/link_uniform_initializers.cpp
src/glsl/nir/nir_lower_io.c
src/glsl/tests/uniform_initializer_utils.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index a45b6e8f026ea449fcaa19a9f395970645bba77c..3b836f8d33ca41cd5e268b8796eef2fe13820b8f 100644 (file)
@@ -1019,6 +1019,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
    case GLSL_TYPE_IMAGE:
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_ATOMIC_UINT:
+   case GLSL_TYPE_SUBROUTINE:
       /* I assume a comparison of a struct containing a sampler just
        * ignores the sampler present in the type.
        */
index cd6df5adad9bbafb81285b9d86a5ba1bcf4cb655..8510671d2f32c7d096830200150153a0fae58bdc 100644 (file)
@@ -32,6 +32,7 @@ mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
 hash_table *glsl_type::array_types = NULL;
 hash_table *glsl_type::record_types = NULL;
 hash_table *glsl_type::interface_types = NULL;
+hash_table *glsl_type::subroutine_types = NULL;
 void *glsl_type::mem_ctx = NULL;
 
 void
@@ -161,6 +162,22 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    mtx_unlock(&glsl_type::mutex);
 }
 
+glsl_type::glsl_type(const char *subroutine_name) :
+   gl_type(0),
+   base_type(GLSL_TYPE_SUBROUTINE),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampler_type(0), interface_packing(0),
+   vector_elements(0), matrix_columns(0),
+   length(0)
+{
+   mtx_lock(&glsl_type::mutex);
+
+   init_ralloc_type_ctx();
+   assert(subroutine_name != NULL);
+   this->name = ralloc_strdup(this->mem_ctx, subroutine_name);
+   this->vector_elements = 1;
+   mtx_unlock(&glsl_type::mutex);
+}
 
 bool
 glsl_type::contains_sampler() const
@@ -231,6 +248,22 @@ glsl_type::contains_opaque() const {
    }
 }
 
+bool
+glsl_type::contains_subroutine() const
+{
+   if (this->is_array()) {
+      return this->fields.array->contains_subroutine();
+   } else if (this->is_record()) {
+      for (unsigned int i = 0; i < this->length; i++) {
+        if (this->fields.structure[i].type->contains_subroutine())
+           return true;
+      }
+      return false;
+   } else {
+      return this->is_subroutine();
+   }
+}
+
 gl_texture_index
 glsl_type::sampler_index() const
 {
@@ -836,6 +869,36 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
    return (glsl_type *) entry->data;
 }
 
+const glsl_type *
+glsl_type::get_subroutine_instance(const char *subroutine_name)
+{
+   const glsl_type key(subroutine_name);
+
+   mtx_lock(&glsl_type::mutex);
+
+   if (subroutine_types == NULL) {
+      subroutine_types = _mesa_hash_table_create(NULL, record_key_hash,
+                                                 record_key_compare);
+   }
+
+   const struct hash_entry *entry = _mesa_hash_table_search(subroutine_types,
+                                                            &key);
+   if (entry == NULL) {
+      mtx_unlock(&glsl_type::mutex);
+      const glsl_type *t = new glsl_type(subroutine_name);
+      mtx_lock(&glsl_type::mutex);
+
+      entry = _mesa_hash_table_insert(subroutine_types, t, (void *) t);
+   }
+
+   assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_SUBROUTINE);
+   assert(strcmp(((glsl_type *) entry->data)->name, subroutine_name) == 0);
+
+   mtx_unlock(&glsl_type::mutex);
+
+   return (glsl_type *) entry->data;
+}
+
 
 const glsl_type *
 glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
@@ -968,6 +1031,7 @@ glsl_type::component_slots() const
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
+   case GLSL_TYPE_SUBROUTINE:
    case GLSL_TYPE_ERROR:
       break;
    }
@@ -988,6 +1052,7 @@ glsl_type::uniform_locations() const
    case GLSL_TYPE_BOOL:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_SUBROUTINE:
       return 1;
 
    case GLSL_TYPE_STRUCT:
@@ -1341,6 +1406,7 @@ glsl_type::count_attribute_slots() const
    case GLSL_TYPE_IMAGE:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
+   case GLSL_TYPE_SUBROUTINE:
    case GLSL_TYPE_ERROR:
       break;
    }
index dff6a9a9d05a9bff41001ec7e18788d3d4dce034..52672b313c06cfe7913216835b94a38dd3cc494e 100644 (file)
@@ -59,6 +59,7 @@ enum glsl_base_type {
    GLSL_TYPE_INTERFACE,
    GLSL_TYPE_ARRAY,
    GLSL_TYPE_VOID,
+   GLSL_TYPE_SUBROUTINE,
    GLSL_TYPE_ERROR
 };
 
@@ -263,6 +264,11 @@ struct glsl_type {
                                                  enum glsl_interface_packing packing,
                                                  const char *block_name);
 
+   /**
+    * Get the instance of an subroutine type
+    */
+   static const glsl_type *get_subroutine_instance(const char *subroutine_name);
+
    /**
     * Get the type resulting from a multiplication of \p type_a * \p type_b
     */
@@ -514,6 +520,13 @@ struct glsl_type {
    /**
     * Query if a type is unnamed/anonymous (named by the parser)
     */
+
+   bool is_subroutine() const
+   {
+      return base_type == GLSL_TYPE_SUBROUTINE;
+   }
+   bool contains_subroutine() const;
+
    bool is_anonymous() const
    {
       return !strncmp(name, "#anon", 5);
@@ -679,6 +692,9 @@ private:
    /** Constructor for array types */
    glsl_type(const glsl_type *array, unsigned length);
 
+   /** Constructor for subroutine types */
+   glsl_type(const char *name);
+
    /** Hash table containing the known array types. */
    static struct hash_table *array_types;
 
@@ -688,6 +704,9 @@ private:
    /** Hash table containing the known interface types. */
    static struct hash_table *interface_types;
 
+   /** Hash table containing the known subroutine types. */
+   static struct hash_table *subroutine_types;
+
    static bool record_key_compare(const void *a, const void *b);
    static unsigned record_key_hash(const void *key);
 
index 8fb7ca40cf10468e346457f775a78be77fa7ce2b..fa1d85a5026703062955a0b0fb42b324f1d068c7 100644 (file)
@@ -260,6 +260,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
    case ir_unop_bit_count:
    case ir_unop_find_msb:
    case ir_unop_find_lsb:
+   case ir_unop_subroutine_to_int:
       this->type = glsl_type::get_instance(GLSL_TYPE_INT,
                                           op0->type->vector_elements, 1);
       break;
@@ -568,6 +569,7 @@ static const char *const operator_strs[] = {
    "frexp_sig",
    "frexp_exp",
    "noise",
+   "subroutine_to_int",
    "interpolate_at_centroid",
    "+",
    "-",
index 98951221b020b458e7dd688db7deb3fef38c9c39..8294b8a19bd281270f2fce1dc2ed718f8bbd40ce 100644 (file)
@@ -1385,6 +1385,7 @@ enum ir_expression_operation {
 
    ir_unop_noise,
 
+   ir_unop_subroutine_to_int,
    /**
     * Interpolate fs input at centroid
     *
index e44b05c991c30753fda5f8046622c4ada4a3c43a..cd03859cac084661b2c67e0e1ad9783c74454fed 100644 (file)
@@ -338,6 +338,12 @@ sign(operand a)
    return expr(ir_unop_sign, a);
 }
 
+ir_expression *
+subr_to_int(operand a)
+{
+   return expr(ir_unop_subroutine_to_int, a);
+}
+
 ir_expression*
 equal(operand a, operand b)
 {
index 870265881138b44b6c72d46ee36353ab1e3fc231..f76453ffcf00166db5e4d4264a4ee11f4a6a4262 100644 (file)
@@ -153,6 +153,7 @@ ir_expression *sqrt(operand a);
 ir_expression *log(operand a);
 ir_expression *sign(operand a);
 
+ir_expression *subr_to_int(operand a);
 ir_expression *equal(operand a, operand b);
 ir_expression *nequal(operand a, operand b);
 ir_expression *less(operand a, operand b);
index 914e0e4d540b33f119cb35d4636014a9cc451d84..49834ffbabf6687266c4bfb0b5984dc71c8bbf95 100644 (file)
@@ -362,6 +362,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_ERROR:
+   case GLSL_TYPE_SUBROUTINE:
    case GLSL_TYPE_INTERFACE:
       assert(!"Should not get here.");
       break;
index 684bef28035f3cbc2d94c3eba19de7266b837eec..3f0dea74e27b76f844a3da9c296e75d7d12b1f72 100644 (file)
@@ -448,6 +448,10 @@ ir_validate::visit_leave(ir_expression *ir)
              ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
       assert(ir->type->base_type == GLSL_TYPE_INT);
       break;
+   case ir_unop_subroutine_to_int:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_SUBROUTINE);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
    case ir_binop_add:
    case ir_binop_sub:
    case ir_binop_mul:
index 6322a2d52cc0e440f0a49f502d59942caf6577ae..d61ae91f4ad0da27dd18630e8bf544dcba02124d 100644 (file)
@@ -89,6 +89,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
       case GLSL_TYPE_ATOMIC_UINT:
       case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_VOID:
+      case GLSL_TYPE_SUBROUTINE:
       case GLSL_TYPE_ERROR:
         /* All other types should have already been filtered by other
          * paths in the caller.
index a9dd77691b2126d229694f895adfee49de5c5fe2..f6e5e2beda4396990a494566be9d151f36a40574 100644 (file)
@@ -59,6 +59,8 @@ type_size(const struct glsl_type *type)
          size += type_size(glsl_get_struct_field(type, i));
       }
       return size;
+   case GLSL_TYPE_SUBROUTINE:
+      return 1;
    case GLSL_TYPE_SAMPLER:
       return 0;
    case GLSL_TYPE_ATOMIC_UINT:
index b90bdcaed3b3e31a67ed9c1972f2a7a25aa68ddd..5006387036f122ddbde95c16e7791cad479c8780 100644 (file)
@@ -102,6 +102,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
       case GLSL_TYPE_VOID:
       case GLSL_TYPE_ERROR:
       case GLSL_TYPE_INTERFACE:
+      case GLSL_TYPE_SUBROUTINE:
         ASSERT_TRUE(false);
         break;
       }
@@ -134,6 +135,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
       case GLSL_TYPE_VOID:
       case GLSL_TYPE_ERROR:
       case GLSL_TYPE_INTERFACE:
+      case GLSL_TYPE_SUBROUTINE:
         ASSERT_TRUE(false);
         break;
       }
@@ -238,6 +240,7 @@ verify_data(gl_constant_value *storage, unsigned storage_array_size,
         case GLSL_TYPE_VOID:
         case GLSL_TYPE_ERROR:
         case GLSL_TYPE_INTERFACE:
+        case GLSL_TYPE_SUBROUTINE:
            ASSERT_TRUE(false);
            break;
         }
index b0fc6254edbc9418ee8c03fd6a3d3f2dc109874b..9553791b07a2f25f1223df00d54d53d3b85e3b56 100644 (file)
@@ -1108,6 +1108,7 @@ type_size(const struct glsl_type *type)
       return size;
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_SUBROUTINE:
       /* Samplers take up one slot in UNIFORMS[], but they're baked in
        * at link time.
        */
@@ -1488,6 +1489,9 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
          result_src = op[0];
       }
       break;
+   case ir_unop_subroutine_to_int:
+      emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
+      break;
    case ir_unop_abs:
       emit_asm(ir, TGSI_OPCODE_ABS, result_dst, op[0]);
       break;