From 491364e1f34ddb2c8ea439e871dd42aaa5cc9b28 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 11 Dec 2012 12:11:16 -0800 Subject: [PATCH] glsl: Add GLSL_TYPE_INTERFACE Interfaces are structurally identical to structures from the compiler's point of view. They have some additional restrictions, and generally GPUs use different instructions to access them. Using a different base type should make this a bit easier. This commit also adds the glsl_type::interface_packing fields. For GLSL_TYPE_INTERFACE types, this will track the specified packing mode. It is analogous to gl_uniform_buffer::_Packing. v2: Add serveral missing GLSL_TYPE_INTERFACE cases in switch-statements. v3: Add information about glsl_type::interface_packing. Move row_major checking in glsl_type::record_key_compare from this patch to the previous patch. Both suggested by Paul Berry. Signed-off-by: Ian Romanick Reviewed-by: Paul Berry Reviewed-by: Kenneth Graunke --- src/glsl/ast_to_hir.cpp | 1 + src/glsl/glsl_types.cpp | 70 +++++++++++++++++-- src/glsl/glsl_types.h | 36 +++++++++- src/glsl/ir_clone.cpp | 1 + src/glsl/link_uniform_initializers.cpp | 1 + src/glsl/tests/uniform_initializer_utils.cpp | 3 + src/mesa/drivers/dri/i965/brw_fs.cpp | 1 + src/mesa/drivers/dri/i965/brw_fs_visitor.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 + 11 files changed, 109 insertions(+), 9 deletions(-) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 301a2591db6..788108dcb0b 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -857,6 +857,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_ERROR: case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_INTERFACE: /* 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 f2dd44acb62..40368ddd0f7 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -34,6 +34,7 @@ extern "C" { hash_table *glsl_type::array_types = NULL; hash_table *glsl_type::record_types = NULL; +hash_table *glsl_type::interface_types = NULL; void *glsl_type::mem_ctx = NULL; void @@ -51,7 +52,7 @@ glsl_type::glsl_type(GLenum gl_type, gl_type(gl_type), base_type(base_type), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), - sampler_type(0), + sampler_type(0), interface_packing(0), vector_elements(vector_elements), matrix_columns(matrix_columns), length(0) { @@ -69,7 +70,7 @@ glsl_type::glsl_type(GLenum gl_type, gl_type(gl_type), base_type(GLSL_TYPE_SAMPLER), sampler_dimensionality(dim), sampler_shadow(shadow), - sampler_array(array), sampler_type(type), + sampler_array(array), sampler_type(type), interface_packing(0), vector_elements(0), matrix_columns(0), length(0) { @@ -82,7 +83,29 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, const char *name) : base_type(GLSL_TYPE_STRUCT), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), - sampler_type(0), + sampler_type(0), interface_packing(0), + vector_elements(0), matrix_columns(0), + length(num_fields) +{ + unsigned int i; + + init_ralloc_type_ctx(); + this->name = ralloc_strdup(this->mem_ctx, name); + this->fields.structure = ralloc_array(this->mem_ctx, + glsl_struct_field, length); + for (i = 0; i < length; i++) { + this->fields.structure[i].type = fields[i].type; + this->fields.structure[i].name = ralloc_strdup(this->fields.structure, + fields[i].name); + this->fields.structure[i].row_major = fields[i].row_major; + } +} + +glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, + enum glsl_interface_packing packing, const char *name) : + base_type(GLSL_TYPE_INTERFACE), + sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), + sampler_type(0), interface_packing((unsigned) packing), vector_elements(0), matrix_columns(0), length(num_fields) { @@ -430,7 +453,7 @@ _mesa_glsl_release_types(void) glsl_type::glsl_type(const glsl_type *array, unsigned length) : base_type(GLSL_TYPE_ARRAY), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), - sampler_type(0), + sampler_type(0), interface_packing(0), vector_elements(0), matrix_columns(0), name(NULL), length(length) { @@ -562,6 +585,9 @@ glsl_type::record_key_compare(const void *a, const void *b) if (key1->length != key2->length) return 1; + if (key1->interface_packing != key2->interface_packing) + return 1; + for (unsigned i = 0; i < key1->length; i++) { if (key1->fields.structure[i].type != key2->fields.structure[i].type) return 1; @@ -624,10 +650,38 @@ glsl_type::get_record_instance(const glsl_struct_field *fields, } +const glsl_type * +glsl_type::get_interface_instance(const glsl_struct_field *fields, + unsigned num_fields, + enum glsl_interface_packing packing, + const char *name) +{ + const glsl_type key(fields, num_fields, packing, name); + + if (interface_types == NULL) { + interface_types = hash_table_ctor(64, record_key_hash, record_key_compare); + } + + const glsl_type *t = (glsl_type *) hash_table_find(interface_types, & key); + if (t == NULL) { + t = new glsl_type(fields, num_fields, packing, name); + + hash_table_insert(interface_types, (void *) t, t); + } + + assert(t->base_type == GLSL_TYPE_INTERFACE); + assert(t->length == num_fields); + assert(strcmp(t->name, name) == 0); + + return t; +} + + const glsl_type * glsl_type::field_type(const char *name) const { - if (this->base_type != GLSL_TYPE_STRUCT) + if (this->base_type != GLSL_TYPE_STRUCT + && this->base_type != GLSL_TYPE_INTERFACE) return error_type; for (unsigned i = 0; i < this->length; i++) { @@ -642,7 +696,8 @@ glsl_type::field_type(const char *name) const int glsl_type::field_index(const char *name) const { - if (this->base_type != GLSL_TYPE_STRUCT) + if (this->base_type != GLSL_TYPE_STRUCT + && this->base_type != GLSL_TYPE_INTERFACE) return -1; for (unsigned i = 0; i < this->length; i++) { @@ -664,7 +719,8 @@ glsl_type::component_slots() const case GLSL_TYPE_BOOL: return this->components(); - case GLSL_TYPE_STRUCT: { + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: { unsigned size = 0; for (unsigned i = 0; i < this->length; i++) diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h index 24ad844cc54..858868507b4 100644 --- a/src/glsl/glsl_types.h +++ b/src/glsl/glsl_types.h @@ -54,6 +54,7 @@ enum glsl_base_type { GLSL_TYPE_BOOL, GLSL_TYPE_SAMPLER, GLSL_TYPE_STRUCT, + GLSL_TYPE_INTERFACE, GLSL_TYPE_ARRAY, GLSL_TYPE_VOID, GLSL_TYPE_ERROR @@ -69,6 +70,12 @@ enum glsl_sampler_dim { GLSL_SAMPLER_DIM_EXTERNAL }; +enum glsl_interface_packing { + GLSL_INTERFACE_PACKING_STD140, + GLSL_INTERFACE_PACKING_SHARED, + GLSL_INTERFACE_PACKING_PACKED +}; + #ifdef __cplusplus #include "GL/gl.h" #include "ralloc.h" @@ -84,6 +91,7 @@ struct glsl_type { * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, * and \c GLSL_TYPE_UINT are valid. */ + unsigned interface_packing:2; /* Callers of this ralloc-based new need not call delete. It's * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */ @@ -130,8 +138,9 @@ struct glsl_type { /** * For \c GLSL_TYPE_ARRAY, this is the length of the array. For - * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and - * the number of values pointed to by \c fields.structure (below). + * \c GLSL_TYPE_STRUCT or \c GLSL_TYPE_INTERFACE, it is the number of + * elements in the structure and the number of values pointed to by + * \c fields.structure (below). */ unsigned length; @@ -231,6 +240,14 @@ struct glsl_type { unsigned num_fields, const char *name); + /** + * Get the instance of an interface block type + */ + static const glsl_type *get_interface_instance(const glsl_struct_field *fields, + unsigned num_fields, + enum glsl_interface_packing packing, + const char *name); + /** * Query the total number of scalars that make up a scalar, vector or matrix */ @@ -393,6 +410,14 @@ struct glsl_type { return base_type == GLSL_TYPE_STRUCT; } + /** + * Query whether or not a type is an interface + */ + bool is_interface() const + { + return base_type == GLSL_TYPE_INTERFACE; + } + /** * Query whether or not a type is the void type singleton. */ @@ -491,6 +516,10 @@ private: glsl_type(const glsl_struct_field *fields, unsigned num_fields, const char *name); + /** Constructor for interface types */ + glsl_type(const glsl_struct_field *fields, unsigned num_fields, + enum glsl_interface_packing packing, const char *name); + /** Constructor for array types */ glsl_type(const glsl_type *array, unsigned length); @@ -500,6 +529,9 @@ private: /** Hash table containing the known record types. */ static struct hash_table *record_types; + /** Hash table containing the known interface types. */ + static struct hash_table *interface_types; + static int record_key_compare(const void *a, const void *b); static unsigned record_key_hash(const void *key); diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 9b7981b5622..3e22f2d2ab0 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -378,6 +378,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const case GLSL_TYPE_SAMPLER: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"Should not get here."); break; } diff --git a/src/glsl/link_uniform_initializers.cpp b/src/glsl/link_uniform_initializers.cpp index 933df29449d..836a360fafd 100644 --- a/src/glsl/link_uniform_initializers.cpp +++ b/src/glsl/link_uniform_initializers.cpp @@ -69,6 +69,7 @@ copy_constant_to_storage(union gl_constant_value *storage, break; case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: /* All other types should have already been filtered by other diff --git a/src/glsl/tests/uniform_initializer_utils.cpp b/src/glsl/tests/uniform_initializer_utils.cpp index e7d274e2a88..a04f5ddc4b2 100644 --- a/src/glsl/tests/uniform_initializer_utils.cpp +++ b/src/glsl/tests/uniform_initializer_utils.cpp @@ -96,6 +96,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type, case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: ASSERT_TRUE(false); break; } @@ -122,6 +123,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type, case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: ASSERT_TRUE(false); break; } @@ -219,6 +221,7 @@ verify_data(gl_constant_value *storage, unsigned storage_array_size, case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: ASSERT_TRUE(false); break; } diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 03b0630a755..8e57eb0fd09 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -457,6 +457,7 @@ fs_visitor::type_size(const struct glsl_type *type) return 0; case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"not reached"); break; } diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 9f6af6f872a..29ad60212a6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -700,6 +700,7 @@ fs_visitor::emit_assignment_writes(fs_reg &l, fs_reg &r, case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"not reached"); break; } diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 6abf714f3a1..ff028c7f4d5 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -287,6 +287,7 @@ brw_type_for_base_type(const struct glsl_type *type) return BRW_REGISTER_TYPE_UD; case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"not reached"); break; } diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 84dcc48341b..64267535155 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -511,6 +511,7 @@ type_size(const struct glsl_type *type) return 1; case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(0); break; } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index fc892fe86cc..4160caa9b7a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -625,6 +625,7 @@ type_size(const struct glsl_type *type) return 1; case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"Invalid type in type_size"); break; } @@ -2536,6 +2537,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, case GLSL_TYPE_VOID: case GLSL_TYPE_STRUCT: case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"Should not get here."); break; } -- 2.30.2