X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fglsl_types.cpp;h=df9c5d36f0b0b1dea091d4a15644e7f2cb6c00f7;hb=f01f754ca13373d62f5f4ba5ff76d83aa4eac62b;hp=bef267fa6be5a81ba61699871bdab49fd1fae8f3;hpb=bcc13b74443137043e8a34f8cb64a5add0d8af93;p=mesa.git diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index bef267fa6be..df9c5d36f0b 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -21,574 +21,509 @@ * DEALINGS IN THE SOFTWARE. */ -#include +#include #include +#include "main/core.h" /* for Elements */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "glsl_types.h" #include "builtin_types.h" -#include "hash_table.h" - +extern "C" { +#include "program/hash_table.h" +} 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; -static void -add_types_to_symbol_table(glsl_symbol_table *symtab, - const struct glsl_type *types, - unsigned num_types, bool warn) +void +glsl_type::init_ralloc_type_ctx(void) { - (void) warn; - - for (unsigned i = 0; i < num_types; i++) { - symtab->add_type(types[i].name, & types[i]); + if (glsl_type::mem_ctx == NULL) { + glsl_type::mem_ctx = ralloc_autofree_context(); + assert(glsl_type::mem_ctx != NULL); } } - -static void -generate_110_types(glsl_symbol_table *symtab) +glsl_type::glsl_type(GLenum gl_type, + glsl_base_type base_type, unsigned vector_elements, + unsigned matrix_columns, const char *name) : + gl_type(gl_type), + base_type(base_type), + sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), + sampler_type(0), interface_packing(0), + vector_elements(vector_elements), matrix_columns(matrix_columns), + length(0) { - add_types_to_symbol_table(symtab, builtin_core_types, - Elements(builtin_core_types), - false); - add_types_to_symbol_table(symtab, builtin_structure_types, - Elements(builtin_structure_types), - false); - add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types, - Elements(builtin_110_deprecated_structure_types), - false); - add_types_to_symbol_table(symtab, & void_type, 1, false); + init_ralloc_type_ctx(); + assert(name != NULL); + this->name = ralloc_strdup(this->mem_ctx, name); + /* Neither dimension is zero or both dimensions are zero. + */ + assert((vector_elements == 0) == (matrix_columns == 0)); + memset(& fields, 0, sizeof(fields)); } - -static void -generate_120_types(glsl_symbol_table *symtab) +glsl_type::glsl_type(GLenum gl_type, + enum glsl_sampler_dim dim, bool shadow, bool array, + unsigned type, const char *name) : + gl_type(gl_type), + base_type(GLSL_TYPE_SAMPLER), + sampler_dimensionality(dim), sampler_shadow(shadow), + sampler_array(array), sampler_type(type), interface_packing(0), + vector_elements(0), matrix_columns(0), + length(0) { - generate_110_types(symtab); - - add_types_to_symbol_table(symtab, builtin_120_types, - Elements(builtin_120_types), false); + init_ralloc_type_ctx(); + assert(name != NULL); + this->name = ralloc_strdup(this->mem_ctx, name); + memset(& fields, 0, sizeof(fields)); } - -static void -generate_130_types(glsl_symbol_table *symtab) +glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, + const char *name) : + gl_type(0), + base_type(GLSL_TYPE_STRUCT), + sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), + sampler_type(0), interface_packing(0), + vector_elements(0), matrix_columns(0), + length(num_fields) { - generate_120_types(symtab); - - add_types_to_symbol_table(symtab, builtin_130_types, - Elements(builtin_130_types), false); + unsigned int i; + + init_ralloc_type_ctx(); + assert(name != NULL); + 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; + } } - -static void -generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, bool warn) +glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, + enum glsl_interface_packing packing, const char *name) : + gl_type(0), + 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) { - add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types, - Elements(builtin_ARB_texture_rectangle_types), - warn); + unsigned int i; + + init_ralloc_type_ctx(); + assert(name != NULL); + 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; + } } - static void -generate_EXT_texture_array_types(glsl_symbol_table *symtab, bool warn) +add_types_to_symbol_table(glsl_symbol_table *symtab, + const struct glsl_type *types, + unsigned num_types, bool warn, + bool skip_1d) { - add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types, - Elements(builtin_EXT_texture_array_types), - warn); -} + (void) warn; + for (unsigned i = 0; i < num_types; i++) { + if (skip_1d && types[i].base_type == GLSL_TYPE_SAMPLER + && types[i].sampler_dimensionality == GLSL_SAMPLER_DIM_1D) + continue; -void -_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) -{ - switch (state->language_version) { - case 110: - generate_110_types(state->symbols); - break; - case 120: - generate_120_types(state->symbols); - break; - case 130: - generate_130_types(state->symbols); - break; - default: - /* error */ - break; + symtab->add_type(types[i].name, & types[i]); } +} - if (state->ARB_texture_rectangle_enable) { - generate_ARB_texture_rectangle_types(state->symbols, - state->ARB_texture_rectangle_warn); +bool +glsl_type::contains_sampler() const +{ + if (this->is_array()) { + return this->fields.array->contains_sampler(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_sampler()) + return true; + } + return false; + } else { + return this->is_sampler(); } +} - if (state->EXT_texture_array_enable && state->language_version < 130) { - // These are already included in 130; don't create twice. - generate_EXT_texture_array_types(state->symbols, - state->EXT_texture_array_warn); + +bool +glsl_type::contains_integer() const +{ + if (this->is_array()) { + return this->fields.array->contains_integer(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_integer()) + return true; + } + return false; + } else { + return this->is_integer(); } } -const glsl_type *glsl_type::get_base_type() const +gl_texture_index +glsl_type::sampler_index() const { - switch (base_type) { - case GLSL_TYPE_UINT: - return uint_type; - case GLSL_TYPE_INT: - return int_type; - case GLSL_TYPE_FLOAT: - return float_type; - case GLSL_TYPE_BOOL: - return bool_type; + const glsl_type *const t = (this->is_array()) ? this->fields.array : this; + + assert(t->is_sampler()); + + switch (t->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: + return (t->sampler_array) ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX; + case GLSL_SAMPLER_DIM_2D: + return (t->sampler_array) ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX; + case GLSL_SAMPLER_DIM_3D: + return TEXTURE_3D_INDEX; + case GLSL_SAMPLER_DIM_CUBE: + return (t->sampler_array) ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX; + case GLSL_SAMPLER_DIM_RECT: + return TEXTURE_RECT_INDEX; + case GLSL_SAMPLER_DIM_BUF: + return TEXTURE_BUFFER_INDEX; + case GLSL_SAMPLER_DIM_EXTERNAL: + return TEXTURE_EXTERNAL_INDEX; + case GLSL_SAMPLER_DIM_MS: + return (t->sampler_array) ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX; default: - return error_type; + assert(!"Should not get here."); + return TEXTURE_BUFFER_INDEX; } } - -ir_function * -glsl_type::generate_constructor(glsl_symbol_table *symtab) const +void +glsl_type::generate_100ES_types(glsl_symbol_table *symtab) { - void *ctx = symtab; - - /* Generate the function name and add it to the symbol table. - */ - ir_function *const f = new(ctx) ir_function(name); - - bool added = symtab->add_function(name, f); - assert(added); - - ir_function_signature *const sig = new(ctx) ir_function_signature(this); - f->add_signature(sig); - - ir_variable **declarations = - (ir_variable **) malloc(sizeof(ir_variable *) * this->length); - for (unsigned i = 0; i < length; i++) { - char *const param_name = (char *) malloc(10); - - snprintf(param_name, 10, "p%08X", i); - - ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY) - ? new(ctx) ir_variable(fields.array, param_name) - : new(ctx) ir_variable(fields.structure[i].type, param_name); - - var->mode = ir_var_in; - declarations[i] = var; - sig->parameters.push_tail(var); - } + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_core_types, + Elements(builtin_core_types), + false, skip_1d); + add_types_to_symbol_table(symtab, builtin_structure_types, + Elements(builtin_structure_types), + false, skip_1d); + add_types_to_symbol_table(symtab, void_type, 1, false, skip_1d); +} - /* Generate the body of the constructor. The body assigns each of the - * parameters to a portion of a local variable called __retval that has - * the same type as the constructor. After initializing __retval, - * __retval is returned. +void +glsl_type::generate_300ES_types(glsl_symbol_table *symtab) +{ + /* GLSL 3.00 ES types are the same as GLSL 1.30 types, except that 1D + * samplers are skipped, and samplerCubeShadow is added. */ - ir_variable *retval = new(ctx) ir_variable(this, "__retval"); - sig->body.push_tail(retval); + bool add_deprecated = false; + bool skip_1d = true; - for (unsigned i = 0; i < length; i++) { - ir_dereference *const lhs = (this->base_type == GLSL_TYPE_ARRAY) - ? (ir_dereference *) new(ctx) ir_dereference_array(retval, - new(ctx) ir_constant(i)) - : (ir_dereference *) new(ctx) ir_dereference_record(retval, - fields.structure[i].name); + generate_130_types(symtab, add_deprecated, skip_1d); - ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[i]); - ir_instruction *const assign = new(ctx) ir_assignment(lhs, rhs, NULL); + add_types_to_symbol_table(symtab, &_samplerCubeShadow_type, 1, false, + skip_1d); +} - sig->body.push_tail(assign); +void +glsl_type::generate_110_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) +{ + generate_100ES_types(symtab); + + add_types_to_symbol_table(symtab, builtin_110_types, + Elements(builtin_110_types), + false, skip_1d); + add_types_to_symbol_table(symtab, &_sampler3D_type, 1, false, skip_1d); + if (add_deprecated) { + add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types, + Elements(builtin_110_deprecated_structure_types), + false, skip_1d); } - - free(declarations); - - ir_dereference *const retref = new(ctx) ir_dereference_variable(retval); - ir_instruction *const inst = new(ctx) ir_return(retref); - sig->body.push_tail(inst); - - return f; } -/** - * Generate the function intro for a constructor - * - * \param type Data type to be constructed - * \param count Number of parameters to this concrete constructor. Most - * types have at least two constructors. One will take a - * single scalar parameter and the other will take "N" - * scalar parameters. - * \param parameters Storage for the list of parameters. These are - * typically stored in an \c ir_function_signature. - * \param declarations Pointers to the variable declarations for the function - * parameters. These are used later to avoid having to use - * the symbol table. - */ -static ir_function_signature * -generate_constructor_intro(void *ctx, - const glsl_type *type, unsigned parameter_count, - ir_variable **declarations) +void +glsl_type::generate_120_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) { - /* Names of parameters used in vector and matrix constructors - */ - static const char *const names[] = { - "a", "b", "c", "d", "e", "f", "g", "h", - "i", "j", "k", "l", "m", "n", "o", "p", - }; - - assert(parameter_count <= Elements(names)); - - const glsl_type *const parameter_type = type->get_base_type(); - - ir_function_signature *const signature = new(ctx) ir_function_signature(type); - - for (unsigned i = 0; i < parameter_count; i++) { - ir_variable *var = new(ctx) ir_variable(parameter_type, names[i]); + generate_110_types(symtab, add_deprecated, skip_1d); - var->mode = ir_var_in; - signature->parameters.push_tail(var); + add_types_to_symbol_table(symtab, builtin_120_types, + Elements(builtin_120_types), false, skip_1d); +} - declarations[i] = var; - } - ir_variable *retval = new(ctx) ir_variable(type, "__retval"); - signature->body.push_tail(retval); +void +glsl_type::generate_130_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) +{ + generate_120_types(symtab, add_deprecated, skip_1d); - declarations[16] = retval; - return signature; + add_types_to_symbol_table(symtab, builtin_130_types, + Elements(builtin_130_types), false, skip_1d); + generate_EXT_texture_array_types(symtab, false); } -/** - * Generate the body of a vector constructor that takes a single scalar - */ -static void -generate_vec_body_from_scalar(void *ctx, - exec_list *instructions, - ir_variable **declarations) +void +glsl_type::generate_140_types(glsl_symbol_table *symtab) { - ir_instruction *inst; - - /* Generate a single assignment of the parameter to __retval.x and return - * __retval.xxxx for however many vector components there are. - */ - ir_dereference *const lhs_ref = - new(ctx) ir_dereference_variable(declarations[16]); - ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[0]); + bool skip_1d = false; - ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); + generate_130_types(symtab, false, skip_1d); - inst = new(ctx) ir_assignment(lhs, rhs, NULL); - instructions->push_tail(inst); + add_types_to_symbol_table(symtab, builtin_140_types, + Elements(builtin_140_types), false, skip_1d); - ir_dereference *const retref = new(ctx) ir_dereference_variable(declarations[16]); + add_types_to_symbol_table(symtab, builtin_EXT_texture_buffer_object_types, + Elements(builtin_EXT_texture_buffer_object_types), + false, skip_1d); +} - ir_swizzle *retval = new(ctx) ir_swizzle(retref, 0, 0, 0, 0, - declarations[16]->type->vector_elements); - inst = new(ctx) ir_return(retval); - instructions->push_tail(inst); +void +glsl_type::generate_150_types(glsl_symbol_table *symtab) +{ + generate_140_types(symtab); + generate_ARB_texture_multisample_types(symtab, false); } -/** - * Generate the body of a vector constructor that takes multiple scalars - */ -static void -generate_vec_body_from_N_scalars(void *ctx, - exec_list *instructions, - ir_variable **declarations) +void +glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, + bool warn) { - ir_instruction *inst; - const glsl_type *const vec_type = declarations[16]->type; + bool skip_1d = false; - /* Generate an assignment of each parameter to a single component of - * __retval.x and return __retval. - */ - for (unsigned i = 0; i < vec_type->vector_elements; i++) { - ir_dereference *const lhs_ref = - new(ctx) ir_dereference_variable(declarations[16]); - ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[i]); - - ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, i, 0, 0, 0, 1); + add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types, + Elements(builtin_ARB_texture_rectangle_types), + warn, skip_1d); +} - inst = new(ctx) ir_assignment(lhs, rhs, NULL); - instructions->push_tail(inst); - } - ir_dereference *retval = new(ctx) ir_dereference_variable(declarations[16]); +void +glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab, + bool warn) +{ + bool skip_1d = false; - inst = new(ctx) ir_return(retval); - instructions->push_tail(inst); + add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types, + Elements(builtin_EXT_texture_array_types), + warn, skip_1d); } -/** - * Generate the body of a matrix constructor that takes a single scalar - */ -static void -generate_mat_body_from_scalar(void *ctx, - exec_list *instructions, - ir_variable **declarations) +void +glsl_type::generate_OES_texture_3D_types(glsl_symbol_table *symtab, bool warn) { - ir_instruction *inst; - - /* Generate an assignment of the parameter to the X component of a - * temporary vector. Set the remaining fields of the vector to 0. The - * size of the vector is equal to the number of rows of the matrix. - * - * Set each column of the matrix to a successive "rotation" of the - * temporary vector. This fills the matrix with 0s, but writes the single - * scalar along the matrix's diagonal. - * - * For a mat4x3, this is equivalent to: - * - * vec3 tmp; - * mat4x3 __retval; - * tmp.x = a; - * tmp.y = 0.0; - * tmp.z = 0.0; - * __retval[0] = tmp.xyy; - * __retval[1] = tmp.yxy; - * __retval[2] = tmp.yyx; - * __retval[3] = tmp.yyy; - */ - const glsl_type *const column_type = declarations[16]->type->column_type(); - const glsl_type *const row_type = declarations[16]->type->row_type(); + bool skip_1d = false; - ir_variable *const column = new(ctx) ir_variable(column_type, "v"); + add_types_to_symbol_table(symtab, &_sampler3D_type, 1, warn, skip_1d); +} - instructions->push_tail(column); - ir_dereference *const lhs_ref = new(ctx) ir_dereference_variable(column); - ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[0]); +void +glsl_type::generate_OES_EGL_image_external_types(glsl_symbol_table *symtab, + bool warn) +{ + bool skip_1d = false; - ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); + add_types_to_symbol_table(symtab, builtin_OES_EGL_image_external_types, + Elements(builtin_OES_EGL_image_external_types), + warn, skip_1d); +} - inst = new(ctx) ir_assignment(lhs, rhs, NULL); - instructions->push_tail(inst); +void +glsl_type::generate_ARB_texture_cube_map_array_types(glsl_symbol_table *symtab, + bool warn) +{ + bool skip_1d = false; - for (unsigned i = 1; i < column_type->vector_elements; i++) { - ir_dereference *const lhs_ref = new(ctx) ir_dereference_variable(column); - ir_constant *const zero = new(ctx) ir_constant(0.0f); + add_types_to_symbol_table(symtab, builtin_ARB_texture_cube_map_array_types, + Elements(builtin_ARB_texture_cube_map_array_types), + warn, skip_1d); +} - ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, i, 0, 0, 0, 1); +void +glsl_type::generate_ARB_texture_multisample_types(glsl_symbol_table *symtab, + bool warn) +{ + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_ARB_texture_multisample_types, + Elements(builtin_ARB_texture_multisample_types), + warn, skip_1d); +} - inst = new(ctx) ir_assignment(lhs, zero, NULL); - instructions->push_tail(inst); +void +_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) +{ + if (state->es_shader) { + switch (state->language_version) { + case 100: + assert(state->es_shader); + glsl_type::generate_100ES_types(state->symbols); + break; + case 300: + glsl_type::generate_300ES_types(state->symbols); + break; + default: + assert(!"Unexpected language version"); + break; + } + } else { + bool skip_1d = false; + switch (state->language_version) { + case 110: + glsl_type::generate_110_types(state->symbols, true, skip_1d); + break; + case 120: + glsl_type::generate_120_types(state->symbols, true, skip_1d); + break; + case 130: + glsl_type::generate_130_types(state->symbols, true, skip_1d); + break; + case 140: + glsl_type::generate_140_types(state->symbols); + break; + case 150: + glsl_type::generate_150_types(state->symbols); + break; + default: + assert(!"Unexpected language version"); + break; + } } - - for (unsigned i = 0; i < row_type->vector_elements; i++) { - static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 }; - ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(column); - - /* This will be .xyyy when i=0, .yxyy when i=1, etc. - */ - ir_swizzle *rhs = new(ctx) ir_swizzle(rhs_ref, swiz[3 - i], swiz[4 - i], - swiz[5 - i], swiz[6 - i], - column_type->vector_elements); - - ir_constant *const idx = new(ctx) ir_constant(int(i)); - ir_dereference *const lhs = - new(ctx) ir_dereference_array(declarations[16], idx); - - inst = new(ctx) ir_assignment(lhs, rhs, NULL); - instructions->push_tail(inst); + if (state->ARB_texture_rectangle_enable || + state->is_version(140, 0)) { + glsl_type::generate_ARB_texture_rectangle_types(state->symbols, + state->ARB_texture_rectangle_warn); + } + if (state->OES_texture_3D_enable + && state->is_version(0, 100)) { + glsl_type::generate_OES_texture_3D_types(state->symbols, + state->OES_texture_3D_warn); } - ir_dereference *const retval = new(ctx) ir_dereference_variable(declarations[16]); - inst = new(ctx) ir_return(retval); - instructions->push_tail(inst); -} - - -/** - * Generate the body of a vector constructor that takes multiple scalars - */ -static void -generate_mat_body_from_N_scalars(void *ctx, - exec_list *instructions, - ir_variable **declarations) -{ - ir_instruction *inst; - const glsl_type *const row_type = declarations[16]->type->row_type(); - const glsl_type *const column_type = declarations[16]->type->column_type(); + if (state->EXT_texture_array_enable + && !state->is_version(130, 0)) { + // These are already included in 130; don't create twice. + glsl_type::generate_EXT_texture_array_types(state->symbols, + state->EXT_texture_array_warn); + } - /* Generate an assignment of each parameter to a single component of - * of a particular column of __retval and return __retval. + /* We cannot check for language_version == 100 here because we need the + * types to support fixed-function program generation. But this is fine + * since the extension is never enabled for OpenGL contexts. */ - for (unsigned i = 0; i < column_type->vector_elements; i++) { - for (unsigned j = 0; j < row_type->vector_elements; j++) { - ir_constant *row_index = new(ctx) ir_constant(int(i)); - ir_dereference *const row_access = - new(ctx) ir_dereference_array(declarations[16], row_index); - - ir_swizzle *component_access = new(ctx) ir_swizzle(row_access, - j, 0, 0, 0, 1); - - const unsigned param = (i * row_type->vector_elements) + j; - ir_dereference *const rhs = - new(ctx) ir_dereference_variable(declarations[param]); - - inst = new(ctx) ir_assignment(component_access, rhs, NULL); - instructions->push_tail(inst); - } + if (state->OES_EGL_image_external_enable) { + glsl_type::generate_OES_EGL_image_external_types(state->symbols, + state->OES_EGL_image_external_warn); } - ir_dereference *retval = new(ctx) ir_dereference_variable(declarations[16]); + if (state->ARB_texture_cube_map_array_enable) { + glsl_type::generate_ARB_texture_cube_map_array_types(state->symbols, + state->ARB_texture_cube_map_array_warn); + } - inst = new(ctx) ir_return(retval); - instructions->push_tail(inst); + if (state->ARB_texture_multisample_enable) { + glsl_type::generate_ARB_texture_multisample_types(state->symbols, + state->ARB_texture_multisample_warn); + } } -/** - * Generate the constructors for a set of GLSL types - * - * Constructor implementations are added to \c instructions, and the symbols - * are added to \c symtab. - */ -static void -generate_constructor(glsl_symbol_table *symtab, const struct glsl_type *types, - unsigned num_types, exec_list *instructions) +const glsl_type *glsl_type::get_base_type() const { - void *ctx = symtab; - ir_variable *declarations[17]; - - for (unsigned i = 0; i < num_types; i++) { - /* Only numeric and boolean vectors and matrices get constructors here. - * Structures need to be handled elsewhere. It is expected that scalar - * constructors are never actually called, so they are not generated. - */ - if (!types[i].is_numeric() && !types[i].is_boolean()) - continue; - - if (types[i].is_scalar()) - continue; - - /* Generate the function block, add it to the symbol table, and emit it. - */ - ir_function *const f = new(ctx) ir_function(types[i].name); - - bool added = symtab->add_function(types[i].name, f); - assert(added); - - instructions->push_tail(f); - - /* Each type has several basic constructors. The total number of forms - * depends on the derived type. - * - * Vectors: 1 scalar, N scalars - * Matrices: 1 scalar, NxM scalars - * - * Several possible types of constructors are not included in this list. - * - * Scalar constructors are not included. The expectation is that the - * IR generator won't actually generate these as constructor calls. The - * expectation is that it will just generate the necessary type - * conversion. - * - * Matrix contructors from matrices are also not included. The - * expectation is that the IR generator will generate a call to the - * appropriate from-scalars constructor. - */ - ir_function_signature *const sig = - generate_constructor_intro(ctx, &types[i], 1, declarations); - f->add_signature(sig); - - if (types[i].is_vector()) { - generate_vec_body_from_scalar(ctx, &sig->body, declarations); - - ir_function_signature *const vec_sig = - generate_constructor_intro(ctx, - &types[i], types[i].vector_elements, - declarations); - f->add_signature(vec_sig); - - generate_vec_body_from_N_scalars(ctx, &vec_sig->body, declarations); - } else { - assert(types[i].is_matrix()); - - generate_mat_body_from_scalar(ctx, &sig->body, declarations); - - ir_function_signature *const mat_sig = - generate_constructor_intro(ctx, - &types[i], - (types[i].vector_elements - * types[i].matrix_columns), - declarations); - f->add_signature(mat_sig); - - generate_mat_body_from_N_scalars(ctx, &mat_sig->body, declarations); - } + switch (base_type) { + case GLSL_TYPE_UINT: + return uint_type; + case GLSL_TYPE_INT: + return int_type; + case GLSL_TYPE_FLOAT: + return float_type; + case GLSL_TYPE_BOOL: + return bool_type; + default: + return error_type; } } -void -generate_110_constructors(glsl_symbol_table *symtab, exec_list *instructions) +const glsl_type *glsl_type::get_scalar_type() const { - generate_constructor(symtab, builtin_core_types, - Elements(builtin_core_types), instructions); -} + const glsl_type *type = this; + /* Handle arrays */ + while (type->base_type == GLSL_TYPE_ARRAY) + type = type->fields.array; -void -generate_120_constructors(glsl_symbol_table *symtab, exec_list *instructions) -{ - generate_110_constructors(symtab, instructions); - - generate_constructor(symtab, builtin_120_types, - Elements(builtin_120_types), instructions); + /* Handle vectors and matrices */ + switch (type->base_type) { + case GLSL_TYPE_UINT: + return uint_type; + case GLSL_TYPE_INT: + return int_type; + case GLSL_TYPE_FLOAT: + return float_type; + case GLSL_TYPE_BOOL: + return bool_type; + default: + /* Handle everything else */ + return type; + } } void -generate_130_constructors(glsl_symbol_table *symtab, exec_list *instructions) +_mesa_glsl_release_types(void) { - generate_120_constructors(symtab, instructions); - - generate_constructor(symtab, builtin_130_types, - Elements(builtin_130_types), instructions); -} - + if (glsl_type::array_types != NULL) { + hash_table_dtor(glsl_type::array_types); + glsl_type::array_types = NULL; + } -void -_mesa_glsl_initialize_constructors(exec_list *instructions, - struct _mesa_glsl_parse_state *state) -{ - switch (state->language_version) { - case 110: - generate_110_constructors(state->symbols, instructions); - break; - case 120: - generate_120_constructors(state->symbols, instructions); - break; - case 130: - generate_130_constructors(state->symbols, instructions); - break; - default: - /* error */ - break; + if (glsl_type::record_types != NULL) { + hash_table_dtor(glsl_type::record_types); + glsl_type::record_types = NULL; } } -glsl_type::glsl_type(void *ctx, const glsl_type *array, unsigned length) : +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) { this->fields.array = array; + /* Inherit the gl type of the base. The GL type is used for + * uniform/statevar handling in Mesa and the arrayness of the type + * is represented by the size rather than the type. + */ + this->gl_type = array->gl_type; /* Allow a maximum of 10 characters for the array size. This is enough * for 32-bits of ~0. The extra 3 are for the '[', ']', and terminating * NUL. */ const unsigned name_length = strlen(array->name) + 10 + 3; - char *const n = (char *) talloc_size(ctx, name_length); + char *const n = (char *) ralloc_size(this->mem_ctx, name_length); if (length == 0) snprintf(n, name_length, "%s[]", array->name); @@ -603,7 +538,7 @@ const glsl_type * glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) { if (base_type == GLSL_TYPE_VOID) - return &void_type; + return void_type; if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4)) return error_type; @@ -657,8 +592,40 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) } +const glsl_type * +glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) +{ + + if (array_types == NULL) { + array_types = hash_table_ctor(64, hash_table_string_hash, + hash_table_string_compare); + } + + /* Generate a name using the base type pointer in the key. This is + * done because the name of the base type may not be unique across + * shaders. For example, two shaders may have different record types + * named 'foo'. + */ + char key[128]; + snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size); + + const glsl_type *t = (glsl_type *) hash_table_find(array_types, key); + if (t == NULL) { + t = new glsl_type(base, array_size); + + hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); + } + + assert(t->base_type == GLSL_TYPE_ARRAY); + assert(t->length == array_size); + assert(t->fields.array == base); + + return t; +} + + int -glsl_type::array_key_compare(const void *a, const void *b) +glsl_type::record_key_compare(const void *a, const void *b) { const glsl_type *const key1 = (glsl_type *) a; const glsl_type *const key2 = (glsl_type *) b; @@ -666,50 +633,99 @@ glsl_type::array_key_compare(const void *a, const void *b) /* Return zero is the types match (there is zero difference) or non-zero * otherwise. */ - return ((key1->fields.array == key2->fields.array) - && (key1->length == key2->length)) ? 0 : 1; + if (strcmp(key1->name, key2->name) != 0) + return 1; + + 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; + if (strcmp(key1->fields.structure[i].name, + key2->fields.structure[i].name) != 0) + return 1; + if (key1->fields.structure[i].row_major + != key2->fields.structure[i].row_major) + return 1; + } + + return 0; } unsigned -glsl_type::array_key_hash(const void *a) +glsl_type::record_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); - const struct { - const glsl_type *t; - unsigned l; - char nul; - } hash_key = { - key->fields.array, - key->length, - '\0' - }; + 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_array_instance(void *ctx, const glsl_type *base, - unsigned array_size) +glsl_type::get_record_instance(const glsl_struct_field *fields, + unsigned num_fields, + const char *name) { - const glsl_type key(ctx, base, array_size); + const glsl_type key(fields, num_fields, name); - if (array_types == NULL) { - array_types = hash_table_ctor(64, array_key_hash, array_key_compare); + if (record_types == NULL) { + record_types = hash_table_ctor(64, record_key_hash, record_key_compare); } - const glsl_type *t = (glsl_type *) hash_table_find(array_types, & key); + const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key); if (t == NULL) { - t = new(ctx) glsl_type(ctx, base, array_size); + t = new glsl_type(fields, num_fields, name); - hash_table_insert(array_types, (void *) t, t); + hash_table_insert(record_types, (void *) t, t); } - assert(t->base_type == GLSL_TYPE_ARRAY); - assert(t->length == array_size); - assert(t->fields.array == base); + assert(t->base_type == GLSL_TYPE_STRUCT); + assert(t->length == num_fields); + assert(strcmp(t->name, name) == 0); + + return t; +} + + +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; } @@ -718,7 +734,8 @@ glsl_type::get_array_instance(void *ctx, const glsl_type *base, 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++) { @@ -733,7 +750,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++) { @@ -755,7 +773,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++) @@ -767,7 +786,246 @@ glsl_type::component_slots() const case GLSL_TYPE_ARRAY: return this->length * this->fields.array->component_slots(); - default: - return 0; + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_VOID: + case GLSL_TYPE_ERROR: + break; + } + + return 0; +} + +bool +glsl_type::can_implicitly_convert_to(const glsl_type *desired) const +{ + if (this == desired) + return true; + + /* There is no conversion among matrix types. */ + if (this->matrix_columns > 1 || desired->matrix_columns > 1) + return false; + + /* int and uint can be converted to float. */ + return desired->is_float() + && this->is_integer() + && this->vector_elements == desired->vector_elements; +} + +unsigned +glsl_type::std140_base_alignment(bool row_major) const +{ + /* (1) If the member is a scalar consuming basic machine units, the + * base alignment is . + * + * (2) If the member is a two- or four-component vector with components + * consuming basic machine units, the base alignment is 2 or + * 4, respectively. + * + * (3) If the member is a three-component vector with components consuming + * basic machine units, the base alignment is 4. + */ + if (this->is_scalar() || this->is_vector()) { + switch (this->vector_elements) { + case 1: + return 4; + case 2: + return 8; + case 3: + case 4: + return 16; + } + } + + /* (4) If the member is an array of scalars or vectors, the base alignment + * and array stride are set to match the base alignment of a single + * array element, according to rules (1), (2), and (3), and rounded up + * to the base alignment of a vec4. The array may have padding at the + * end; the base offset of the member following the array is rounded up + * to the next multiple of the base alignment. + * + * (6) If the member is an array of column-major matrices with + * columns and rows, the matrix is stored identically to a row of + * * column vectors with components each, according to rule + * (4). + * + * (8) If the member is an array of row-major matrices with columns + * and rows, the matrix is stored identically to a row of * + * row vectors with components each, according to rule (4). + * + * (10) If the member is an array of structures, the elements of + * the array are laid out in order, according to rule (9). + */ + if (this->is_array()) { + if (this->fields.array->is_scalar() || + this->fields.array->is_vector() || + this->fields.array->is_matrix()) { + return MAX2(this->fields.array->std140_base_alignment(row_major), 16); + } else { + assert(this->fields.array->is_record()); + return this->fields.array->std140_base_alignment(row_major); + } + } + + /* (5) If the member is a column-major matrix with columns and + * rows, the matrix is stored identically to an array of + * column vectors with components each, according to + * rule (4). + * + * (7) If the member is a row-major matrix with columns and + * rows, the matrix is stored identically to an array of + * row vectors with components each, according to rule (4). + */ + if (this->is_matrix()) { + const struct glsl_type *vec_type, *array_type; + int c = this->matrix_columns; + int r = this->vector_elements; + + if (row_major) { + vec_type = get_instance(GLSL_TYPE_FLOAT, c, 1); + array_type = glsl_type::get_array_instance(vec_type, r); + } else { + vec_type = get_instance(GLSL_TYPE_FLOAT, r, 1); + array_type = glsl_type::get_array_instance(vec_type, c); + } + + return array_type->std140_base_alignment(false); + } + + /* (9) If the member is a structure, the base alignment of the + * structure is , where is the largest base alignment + * value of any of its members, and rounded up to the base + * alignment of a vec4. The individual members of this + * sub-structure are then assigned offsets by applying this set + * of rules recursively, where the base offset of the first + * member of the sub-structure is equal to the aligned offset + * of the structure. The structure may have padding at the end; + * the base offset of the member following the sub-structure is + * rounded up to the next multiple of the base alignment of the + * structure. + */ + if (this->is_record()) { + unsigned base_alignment = 16; + for (unsigned i = 0; i < this->length; i++) { + const struct glsl_type *field_type = this->fields.structure[i].type; + base_alignment = MAX2(base_alignment, + field_type->std140_base_alignment(row_major)); + } + return base_alignment; } + + assert(!"not reached"); + return -1; +} + +unsigned +glsl_type::std140_size(bool row_major) const +{ + /* (1) If the member is a scalar consuming basic machine units, the + * base alignment is . + * + * (2) If the member is a two- or four-component vector with components + * consuming basic machine units, the base alignment is 2 or + * 4, respectively. + * + * (3) If the member is a three-component vector with components consuming + * basic machine units, the base alignment is 4. + */ + if (this->is_scalar() || this->is_vector()) { + return this->vector_elements * 4; + } + + /* (5) If the member is a column-major matrix with columns and + * rows, the matrix is stored identically to an array of + * column vectors with components each, according to + * rule (4). + * + * (6) If the member is an array of column-major matrices with + * columns and rows, the matrix is stored identically to a row of + * * column vectors with components each, according to rule + * (4). + * + * (7) If the member is a row-major matrix with columns and + * rows, the matrix is stored identically to an array of + * row vectors with components each, according to rule (4). + * + * (8) If the member is an array of row-major matrices with columns + * and rows, the matrix is stored identically to a row of * + * row vectors with components each, according to rule (4). + */ + if (this->is_matrix() || (this->is_array() && + this->fields.array->is_matrix())) { + const struct glsl_type *element_type; + const struct glsl_type *vec_type; + unsigned int array_len; + + if (this->is_array()) { + element_type = this->fields.array; + array_len = this->length; + } else { + element_type = this; + array_len = 1; + } + + if (row_major) { + vec_type = get_instance(GLSL_TYPE_FLOAT, + element_type->matrix_columns, 1); + array_len *= element_type->vector_elements; + } else { + vec_type = get_instance(GLSL_TYPE_FLOAT, + element_type->vector_elements, 1); + array_len *= element_type->matrix_columns; + } + const glsl_type *array_type = glsl_type::get_array_instance(vec_type, + array_len); + + return array_type->std140_size(false); + } + + /* (4) If the member is an array of scalars or vectors, the base alignment + * and array stride are set to match the base alignment of a single + * array element, according to rules (1), (2), and (3), and rounded up + * to the base alignment of a vec4. The array may have padding at the + * end; the base offset of the member following the array is rounded up + * to the next multiple of the base alignment. + * + * (10) If the member is an array of structures, the elements of + * the array are laid out in order, according to rule (9). + */ + if (this->is_array()) { + if (this->fields.array->is_record()) { + return this->length * this->fields.array->std140_size(row_major); + } else { + unsigned element_base_align = + this->fields.array->std140_base_alignment(row_major); + return this->length * MAX2(element_base_align, 16); + } + } + + /* (9) If the member is a structure, the base alignment of the + * structure is , where is the largest base alignment + * value of any of its members, and rounded up to the base + * alignment of a vec4. The individual members of this + * sub-structure are then assigned offsets by applying this set + * of rules recursively, where the base offset of the first + * member of the sub-structure is equal to the aligned offset + * of the structure. The structure may have padding at the end; + * the base offset of the member following the sub-structure is + * rounded up to the next multiple of the base alignment of the + * structure. + */ + if (this->is_record()) { + unsigned size = 0; + for (unsigned i = 0; i < this->length; i++) { + const struct glsl_type *field_type = this->fields.structure[i].type; + unsigned align = field_type->std140_base_alignment(row_major); + size = glsl_align(size, align); + size += field_type->std140_size(row_major); + } + size = glsl_align(size, + this->fields.structure[0].type->std140_base_alignment(row_major)); + return size; + } + + assert(!"not reached"); + return -1; }