glsl/types: Add support for function types
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 10 Feb 2016 02:17:06 +0000 (18:17 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sun, 14 Feb 2016 01:22:36 +0000 (17:22 -0800)
SPIR-V has a concept of a function type that's used fairly heavily.  We
could special-case function types in SPIR-V -> NIR but it's easier if we
just add support to glsl_types.

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/ir_clone.cpp
src/compiler/glsl/link_uniform_initializers.cpp
src/compiler/glsl/tests/uniform_initializer_utils.cpp
src/compiler/glsl_types.cpp
src/compiler/glsl_types.h
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 3996b01c9f92fe584054c76fbb432919584e1bf2..b63937899cb8d8ce8127caa8a1758ddef3f5790f 100644 (file)
@@ -1135,6 +1135,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_SUBROUTINE:
+   case GLSL_TYPE_FUNCTION:
       /* I assume a comparison of a struct containing a sampler just
        * ignores the sampler present in the type.
        */
index 0965b0d3719d9c611048854f85ff402fba7ee3a4..43ffffb0a38defc12943b732620a7f015021207e 100644 (file)
@@ -373,6 +373,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_SUBROUTINE:
    case GLSL_TYPE_INTERFACE:
+   case GLSL_TYPE_FUNCTION:
       assert(!"Should not get here.");
       break;
    }
index 58d21e5125efe666e0e8f52e37adfec669dd9a89..3609f81771e127baeae9a3ab89c8df9f823b9401 100644 (file)
@@ -90,6 +90,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
       case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_VOID:
       case GLSL_TYPE_SUBROUTINE:
+      case GLSL_TYPE_FUNCTION:
       case GLSL_TYPE_ERROR:
         /* All other types should have already been filtered by other
          * paths in the caller.
index 5006387036f122ddbde95c16e7791cad479c8780..ec64be18cb36ddabffa5ee96a0fd76d1272c4729 100644 (file)
@@ -103,6 +103,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
       case GLSL_TYPE_ERROR:
       case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_SUBROUTINE:
+      case GLSL_TYPE_FUNCTION:
         ASSERT_TRUE(false);
         break;
       }
@@ -136,6 +137,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type,
       case GLSL_TYPE_ERROR:
       case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_SUBROUTINE:
+      case GLSL_TYPE_FUNCTION:
         ASSERT_TRUE(false);
         break;
       }
@@ -241,6 +243,7 @@ verify_data(gl_constant_value *storage, unsigned storage_array_size,
         case GLSL_TYPE_ERROR:
         case GLSL_TYPE_INTERFACE:
         case GLSL_TYPE_SUBROUTINE:
+         case GLSL_TYPE_FUNCTION:
            ASSERT_TRUE(false);
            break;
         }
index f412f897be40035de7d958bc8b646844bf00aff7..901baa313b9cf712a7ef9ddb45988c0b383992fd 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::function_types = NULL;
 hash_table *glsl_type::subroutine_types = NULL;
 void *glsl_type::mem_ctx = NULL;
 
@@ -174,6 +175,39 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    mtx_unlock(&glsl_type::mutex);
 }
 
+glsl_type::glsl_type(const glsl_type *return_type,
+                     const glsl_function_param *params, unsigned num_params) :
+   gl_type(0),
+   base_type(GLSL_TYPE_FUNCTION),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampled_type(0), interface_packing(0),
+   vector_elements(0), matrix_columns(0),
+   length(num_params)
+{
+   unsigned int i;
+
+   mtx_lock(&glsl_type::mutex);
+
+   init_ralloc_type_ctx();
+
+   this->fields.parameters = rzalloc_array(this->mem_ctx,
+                                           glsl_function_param, num_params + 1);
+
+   /* We store the return type as the first parameter */
+   this->fields.parameters[0].type = return_type;
+   this->fields.parameters[0].in = false;
+   this->fields.parameters[0].out = true;
+
+   /* We store the i'th parameter in slot i+1 */
+   for (i = 0; i < length; i++) {
+      this->fields.parameters[i + 1].type = params[i].type;
+      this->fields.parameters[i + 1].in = params[i].in;
+      this->fields.parameters[i + 1].out = params[i].out;
+   }
+
+   mtx_unlock(&glsl_type::mutex);
+}
+
 glsl_type::glsl_type(const char *subroutine_name) :
    gl_type(0),
    base_type(GLSL_TYPE_SUBROUTINE),
@@ -929,6 +963,74 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
 }
 
 
+static bool
+function_key_compare(const void *a, const void *b)
+{
+   const glsl_type *const key1 = (glsl_type *) a;
+   const glsl_type *const key2 = (glsl_type *) b;
+
+   if (key1->length != key2->length)
+      return 1;
+
+   return memcmp(key1->fields.parameters, key2->fields.parameters,
+                 (key1->length + 1) * sizeof(*key1->fields.parameters)) == 0;
+}
+
+
+static uint32_t
+function_key_hash(const void *a)
+{
+   const glsl_type *const key = (glsl_type *) a;
+   char hash_key[128];
+   unsigned size = 0;
+
+   size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
+
+   for (unsigned i = 0; i < key->length; i++) {
+      if (size >= sizeof(hash_key))
+        break;
+
+      size += snprintf(& hash_key[size], sizeof(hash_key) - size,
+                      "%p", (void *) key->fields.structure[i].type);
+   }
+
+   return _mesa_hash_string(hash_key);
+}
+
+const glsl_type *
+glsl_type::get_function_instance(const glsl_type *return_type,
+                                 const glsl_function_param *params,
+                                 unsigned num_params)
+{
+   const glsl_type key(return_type, params, num_params);
+
+   mtx_lock(&glsl_type::mutex);
+
+   if (function_types == NULL) {
+      function_types = _mesa_hash_table_create(NULL, function_key_hash,
+                                               function_key_compare);
+   }
+
+   struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
+   if (entry == NULL) {
+      mtx_unlock(&glsl_type::mutex);
+      const glsl_type *t = new glsl_type(return_type, params, num_params);
+      mtx_lock(&glsl_type::mutex);
+
+      entry = _mesa_hash_table_insert(function_types, t, (void *) t);
+   }
+
+   const glsl_type *t = (const glsl_type *)entry->data;
+
+   assert(t->base_type == GLSL_TYPE_FUNCTION);
+   assert(t->length == num_params);
+
+   mtx_unlock(&glsl_type::mutex);
+
+   return t;
+}
+
+
 const glsl_type *
 glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
 {
@@ -1058,6 +1160,8 @@ glsl_type::component_slots() const
       return 1;
    case GLSL_TYPE_SUBROUTINE:
      return 1;
+
+   case GLSL_TYPE_FUNCTION:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
@@ -1703,6 +1807,7 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
    case GLSL_TYPE_ARRAY:
       return this->length * this->fields.array->count_attribute_slots(vertex_input_slots);
 
+   case GLSL_TYPE_FUNCTION:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
    case GLSL_TYPE_ATOMIC_UINT:
index 1d9cfd4c869d271001dc9c7e8707854a19dd4b37..7bc082751c6464531e86409e239ef9ec9c5e776d 100644 (file)
@@ -60,6 +60,7 @@ enum glsl_base_type {
    GLSL_TYPE_ARRAY,
    GLSL_TYPE_VOID,
    GLSL_TYPE_SUBROUTINE,
+   GLSL_TYPE_FUNCTION,
    GLSL_TYPE_ERROR
 };
 
@@ -187,7 +188,7 @@ struct glsl_type {
     */
    union {
       const struct glsl_type *array;            /**< Type of array elements. */
-      const struct glsl_type *parameters;       /**< Parameters to function. */
+      struct glsl_function_param *parameters;   /**< Parameters to function. */
       struct glsl_struct_field *structure;      /**< List of struct fields. */
    } fields;
 
@@ -277,6 +278,13 @@ struct glsl_type {
     */
    static const glsl_type *get_subroutine_instance(const char *subroutine_name);
 
+   /**
+    * Get the instance of a function type
+    */
+   static const glsl_type *get_function_instance(const struct glsl_type *return_type,
+                                                 const glsl_function_param *parameters,
+                                                 unsigned num_params);
+
    /**
     * Get the type resulting from a multiplication of \p type_a * \p type_b
     */
@@ -758,6 +766,10 @@ private:
    glsl_type(const glsl_struct_field *fields, unsigned num_fields,
             enum glsl_interface_packing packing, const char *name);
 
+   /** Constructor for interface types */
+   glsl_type(const glsl_type *return_type,
+             const glsl_function_param *params, unsigned num_params);
+
    /** Constructor for array types */
    glsl_type(const glsl_type *array, unsigned length);
 
@@ -776,6 +788,9 @@ private:
    /** Hash table containing the known subroutine types. */
    static struct hash_table *subroutine_types;
 
+   /** Hash table containing the known function types. */
+   static struct hash_table *function_types;
+
    static bool record_key_compare(const void *a, const void *b);
    static unsigned record_key_hash(const void *key);
 
@@ -875,6 +890,13 @@ struct glsl_struct_field {
    }
 };
 
+struct glsl_function_param {
+   const struct glsl_type *type;
+
+   bool in;
+   bool out;
+};
+
 static inline unsigned int
 glsl_align(unsigned int a, unsigned int align)
 {
index 80939b362080482c7f792ef2e526c63d50cb017a..41b10a45105cae0945d089fe6c06e4d797e606d2 100644 (file)
@@ -510,6 +510,7 @@ type_size_scalar(const struct glsl_type *type)
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_FUNCTION:
       unreachable("not reached");
    }
 
index 8518622c0b6aa57af44211d1a7b9e5145b9ebb62..91e47800e1f3f1d9b3db7d7d897c2f2c7d3f07ff 100644 (file)
@@ -84,6 +84,7 @@ brw_type_for_base_type(const struct glsl_type *type)
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_FUNCTION:
       unreachable("not reached");
    }
 
index 96dbc3760011119591563cd49e8630fbe6c42c6f..6a8c76c4ea06a3b8546729634a93958782812f43 100644 (file)
@@ -622,6 +622,7 @@ type_size_vec4(const struct glsl_type *type)
    case GLSL_TYPE_DOUBLE:
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_INTERFACE:
+   case GLSL_TYPE_FUNCTION:
       unreachable("not reached");
    }
 
index bbc7a7d3b4e7203afdff1419f1e5f90817c23ee6..495048d4bfcab9f60063bd958473ffae6240256d 100644 (file)
@@ -541,6 +541,7 @@ type_size(const struct glsl_type *type)
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_INTERFACE:
+   case GLSL_TYPE_FUNCTION:
       assert(!"Invalid type in type_size");
       break;
    }
@@ -2521,6 +2522,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
          case GLSL_TYPE_STRUCT:
          case GLSL_TYPE_ERROR:
          case GLSL_TYPE_INTERFACE:
+         case GLSL_TYPE_FUNCTION:
            assert(!"Should not get here.");
            break;
         }
index 436de87ec1ed72a9dcfe2751325f112232cad5f8..67f1504c877cac238c8b83766d2ad634c7f5ad99 100644 (file)
@@ -1216,6 +1216,7 @@ attrib_type_size(const struct glsl_type *type, bool is_vs_input)
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_ERROR:
+   case GLSL_TYPE_FUNCTION:
       assert(!"Invalid type in type_size");
       break;
    }