From 95ea9f770878517364ac2161eb943afbc77bfef9 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 9 Feb 2016 18:17:06 -0800 Subject: [PATCH] glsl/types: Add support for function types 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 --- src/compiler/glsl/ast_to_hir.cpp | 1 + src/compiler/glsl/ir_clone.cpp | 1 + .../glsl/link_uniform_initializers.cpp | 1 + .../glsl/tests/uniform_initializer_utils.cpp | 3 + src/compiler/glsl_types.cpp | 105 ++++++++++++++++++ src/compiler/glsl_types.h | 24 +++- src/mesa/drivers/dri/i965/brw_fs.cpp | 1 + src/mesa/drivers/dri/i965/brw_shader.cpp | 1 + .../drivers/dri/i965/brw_vec4_visitor.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 2 + src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 1 + 11 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 3996b01c9f9..b63937899cb 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -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. */ diff --git a/src/compiler/glsl/ir_clone.cpp b/src/compiler/glsl/ir_clone.cpp index 0965b0d3719..43ffffb0a38 100644 --- a/src/compiler/glsl/ir_clone.cpp +++ b/src/compiler/glsl/ir_clone.cpp @@ -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; } diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp index 58d21e5125e..3609f81771e 100644 --- a/src/compiler/glsl/link_uniform_initializers.cpp +++ b/src/compiler/glsl/link_uniform_initializers.cpp @@ -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. diff --git a/src/compiler/glsl/tests/uniform_initializer_utils.cpp b/src/compiler/glsl/tests/uniform_initializer_utils.cpp index 5006387036f..ec64be18cb3 100644 --- a/src/compiler/glsl/tests/uniform_initializer_utils.cpp +++ b/src/compiler/glsl/tests/uniform_initializer_utils.cpp @@ -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; } diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index f412f897be4..901baa313b9 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/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; 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: diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index 1d9cfd4c869..7bc082751c6 100644 --- a/src/compiler/glsl_types.h +++ b/src/compiler/glsl_types.h @@ -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) { diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 80939b36208..41b10a45105 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -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"); } diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 8518622c0b6..91e47800e1f 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -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"); } diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 96dbc376001..6a8c76c4ea0 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -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"); } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index bbc7a7d3b4e..495048d4bfc 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -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; } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 436de87ec1e..67f1504c877 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -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; } -- 2.30.2