From: Dave Airlie Date: Mon, 20 Apr 2015 00:16:55 +0000 (+1000) Subject: glsl/types: add new subroutine type (v3.2) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=57f24299b7fe0f7b20c2a3cf1e94c747825b568d;p=mesa.git glsl/types: add new subroutine type (v3.2) 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 Reviewed-by: Chris Forbes Signed-off-by: Dave Airlie tests: fix warnings --- diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index a45b6e8f026..3b836f8d33c 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -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. */ diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index cd6df5adad9..8510671d2f3 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::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; } diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h index dff6a9a9d05..52672b313c0 100644 --- a/src/glsl/glsl_types.h +++ b/src/glsl/glsl_types.h @@ -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); diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 8fb7ca40cf1..fa1d85a5026 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -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", "+", "-", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 98951221b02..8294b8a19bd 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1385,6 +1385,7 @@ enum ir_expression_operation { ir_unop_noise, + ir_unop_subroutine_to_int, /** * Interpolate fs input at centroid * diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp index e44b05c991c..cd03859cac0 100644 --- a/src/glsl/ir_builder.cpp +++ b/src/glsl/ir_builder.cpp @@ -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) { diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h index 87026588113..f76453ffcf0 100644 --- a/src/glsl/ir_builder.h +++ b/src/glsl/ir_builder.h @@ -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); diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 914e0e4d540..49834ffbabf 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -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; diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 684bef28035..3f0dea74e27 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -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: diff --git a/src/glsl/link_uniform_initializers.cpp b/src/glsl/link_uniform_initializers.cpp index 6322a2d52cc..d61ae91f4ad 100644 --- a/src/glsl/link_uniform_initializers.cpp +++ b/src/glsl/link_uniform_initializers.cpp @@ -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. diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c index a9dd77691b2..f6e5e2beda4 100644 --- a/src/glsl/nir/nir_lower_io.c +++ b/src/glsl/nir/nir_lower_io.c @@ -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: diff --git a/src/glsl/tests/uniform_initializer_utils.cpp b/src/glsl/tests/uniform_initializer_utils.cpp index b90bdcaed3b..5006387036f 100644 --- a/src/glsl/tests/uniform_initializer_utils.cpp +++ b/src/glsl/tests/uniform_initializer_utils.cpp @@ -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; } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index b0fc6254edb..9553791b07a 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -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;