glsl/types: Add support for function types
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 25 Feb 2015 00:29:33 +0000 (16:29 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sat, 16 May 2015 18:16:32 +0000 (11:16 -0700)
src/glsl/glsl_types.cpp
src/glsl/glsl_types.h

index 3ee5c00b22d3dd9a569901e15b725c496aea1a1b..0d83ee68e427d5d095a8ba0831ff99769ab2da72 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;
 void *glsl_type::mem_ctx = NULL;
 
 void
@@ -159,6 +160,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),
+   sampler_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);
+}
+
 
 bool
 glsl_type::contains_sampler() const
@@ -827,6 +861,72 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
 }
 
 
+static int
+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));
+}
+
+
+static unsigned
+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 hash_table_string_hash(& 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 = hash_table_ctor(64, function_key_hash,
+                                       function_key_compare);
+   }
+
+   const glsl_type *t = (glsl_type *) hash_table_find(function_types, &key);
+   if (t == NULL) {
+      mtx_unlock(&glsl_type::mutex);
+      t = new glsl_type(return_type, params, num_params);
+      mtx_lock(&glsl_type::mutex);
+
+      hash_table_insert(function_types, (void *) t, t);
+   }
+
+   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)
 {
index c77e337bf63352fd833b37c4ba0becd24b69870b..4d726c6bcf9e45730788aa7fb28b5c99f9c39bcb 100644 (file)
@@ -179,7 +179,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;
 
@@ -276,6 +276,13 @@ struct glsl_type {
                                                  enum glsl_interface_packing packing,
                                                  const char *block_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
     */
@@ -689,6 +696,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);
 
@@ -701,6 +712,9 @@ private:
    /** Hash table containing the known interface types. */
    static struct hash_table *interface_types;
 
+   /** Hash table containing the known function types. */
+   static struct hash_table *function_types;
+
    static int record_key_compare(const void *a, const void *b);
    static unsigned record_key_hash(const void *key);
 
@@ -771,6 +785,13 @@ struct glsl_struct_field {
    int stream;
 };
 
+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)
 {