From: Jason Ekstrand Date: Wed, 25 Feb 2015 00:29:33 +0000 (-0800) Subject: glsl/types: Add support for function types X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=053778c49362d49db93335d46cdafaa760038ac4;p=mesa.git glsl/types: Add support for function types --- diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 3ee5c00b22d..0d83ee68e42 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -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) { diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h index c77e337bf63..4d726c6bcf9 100644 --- a/src/glsl/glsl_types.h +++ b/src/glsl/glsl_types.h @@ -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) {