X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fglsl_types.cpp;h=0d2eb7cec0980093fdbabdffcec1e70af818056c;hb=d7e482d32cf0188a1ed49e76f008837be5cfd720;hp=f78d2a6f8d8cae10552366309a5504f20e54916c;hpb=500b69e7973a8320d76cc7e8a3f1761641bed433;p=mesa.git diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index f78d2a6f8d8..0d2eb7cec09 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -22,16 +22,13 @@ */ #include -#include -#include "main/core.h" /* for Elements */ -#include "glsl_symbol_table.h" +#include "main/core.h" /* for Elements, MAX2 */ #include "glsl_parser_extras.h" #include "glsl_types.h" -#include "builtin_types.h" -extern "C" { #include "program/hash_table.h" -} + +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; @@ -56,27 +53,45 @@ glsl_type::glsl_type(GLenum gl_type, vector_elements(vector_elements), matrix_columns(matrix_columns), length(0) { + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); + assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); + + mtx_unlock(&glsl_type::mutex); + /* Neither dimension is zero or both dimensions are zero. */ assert((vector_elements == 0) == (matrix_columns == 0)); memset(& fields, 0, sizeof(fields)); } -glsl_type::glsl_type(GLenum gl_type, +glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, enum glsl_sampler_dim dim, bool shadow, bool array, unsigned type, const char *name) : gl_type(gl_type), - base_type(GLSL_TYPE_SAMPLER), + base_type(base_type), sampler_dimensionality(dim), sampler_shadow(shadow), sampler_array(array), sampler_type(type), interface_packing(0), - vector_elements(0), matrix_columns(0), length(0) { + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); + assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); + + mtx_unlock(&glsl_type::mutex); + memset(& fields, 0, sizeof(fields)); + + if (base_type == GLSL_TYPE_SAMPLER) { + /* Samplers take no storage whatsoever. */ + matrix_columns = vector_elements = 0; + } else { + matrix_columns = vector_elements = 1; + } } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -90,16 +105,26 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, { unsigned int i; + mtx_lock(&glsl_type::mutex); + 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; + this->fields.structure[i].location = fields[i].location; + this->fields.structure[i].interpolation = fields[i].interpolation; + this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; + this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } + + mtx_unlock(&glsl_type::mutex); } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -113,7 +138,10 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, { unsigned int i; + mtx_lock(&glsl_type::mutex); + 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); @@ -121,27 +149,17 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, 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; + this->fields.structure[i].location = fields[i].location; + this->fields.structure[i].interpolation = fields[i].interpolation; + this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; + this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } -} -static void -add_types_to_symbol_table(glsl_symbol_table *symtab, - const struct glsl_type *types, - unsigned num_types, bool warn, - bool skip_1d) -{ - (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; - - symtab->add_type(types[i].name, & types[i]); - } + mtx_unlock(&glsl_type::mutex); } + bool glsl_type::contains_sampler() const { @@ -175,6 +193,25 @@ glsl_type::contains_integer() const } } +bool +glsl_type::contains_opaque() const { + switch (base_type) { + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: + case GLSL_TYPE_ATOMIC_UINT: + return true; + case GLSL_TYPE_ARRAY: + return element_type()->contains_opaque(); + case GLSL_TYPE_STRUCT: + for (unsigned int i = 0; i < length; i++) { + if (fields.structure[i].type->contains_opaque()) + return true; + } + return false; + default: + return false; + } +} gl_texture_index glsl_type::sampler_index() const @@ -198,224 +235,30 @@ glsl_type::sampler_index() const 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: assert(!"Should not get here."); return TEXTURE_BUFFER_INDEX; } } -void -glsl_type::generate_100ES_types(glsl_symbol_table *symtab) -{ - 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); -} - -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. - */ - bool add_deprecated = false; - bool skip_1d = true; - - generate_130_types(symtab, add_deprecated, skip_1d); - - add_types_to_symbol_table(symtab, &_samplerCubeShadow_type, 1, false, - skip_1d); -} - -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); - } -} - - -void -glsl_type::generate_120_types(glsl_symbol_table *symtab, bool add_deprecated, - bool skip_1d) -{ - generate_110_types(symtab, add_deprecated, skip_1d); - - add_types_to_symbol_table(symtab, builtin_120_types, - Elements(builtin_120_types), false, skip_1d); -} - - -void -glsl_type::generate_130_types(glsl_symbol_table *symtab, bool add_deprecated, - bool skip_1d) -{ - generate_120_types(symtab, add_deprecated, skip_1d); - - add_types_to_symbol_table(symtab, builtin_130_types, - Elements(builtin_130_types), false, skip_1d); - generate_EXT_texture_array_types(symtab, false); -} - - -void -glsl_type::generate_140_types(glsl_symbol_table *symtab) -{ - bool skip_1d = false; - - generate_130_types(symtab, false, skip_1d); - - add_types_to_symbol_table(symtab, builtin_140_types, - Elements(builtin_140_types), false, skip_1d); - - add_types_to_symbol_table(symtab, builtin_EXT_texture_buffer_object_types, - Elements(builtin_EXT_texture_buffer_object_types), - false, skip_1d); -} - - -void -glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, - bool warn) -{ - bool skip_1d = false; - - add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types, - Elements(builtin_ARB_texture_rectangle_types), - warn, skip_1d); -} - - -void -glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab, - bool warn) -{ - bool skip_1d = false; - - add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types, - Elements(builtin_EXT_texture_array_types), - warn, skip_1d); -} - - -void -glsl_type::generate_OES_texture_3D_types(glsl_symbol_table *symtab, bool warn) -{ - bool skip_1d = false; - - add_types_to_symbol_table(symtab, &_sampler3D_type, 1, warn, skip_1d); -} - - -void -glsl_type::generate_OES_EGL_image_external_types(glsl_symbol_table *symtab, - bool warn) -{ - bool skip_1d = false; - - add_types_to_symbol_table(symtab, builtin_OES_EGL_image_external_types, - Elements(builtin_OES_EGL_image_external_types), - warn, skip_1d); -} - -void -glsl_type::generate_ARB_texture_cube_map_array_types(glsl_symbol_table *symtab, - bool warn) +bool +glsl_type::contains_image() const { - bool skip_1d = false; - - add_types_to_symbol_table(symtab, builtin_ARB_texture_cube_map_array_types, - Elements(builtin_ARB_texture_cube_map_array_types), - warn, skip_1d); -} - -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; + if (this->is_array()) { + return this->fields.array->contains_image(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_image()) + return true; } + return false; } 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: - case 150: - glsl_type::generate_140_types(state->symbols); - break; - default: - assert(!"Unexpected language version"); - break; - } - } - - 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); - } - - 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); - } - - /* 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. - */ - if (state->OES_EGL_image_external_enable) { - glsl_type::generate_OES_EGL_image_external_types(state->symbols, - state->OES_EGL_image_external_warn); - } - - 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); + return this->is_image(); } } - const glsl_type *glsl_type::get_base_type() const { switch (base_type) { @@ -449,6 +292,8 @@ const glsl_type *glsl_type::get_scalar_type() const return int_type; case GLSL_TYPE_FLOAT: return float_type; + case GLSL_TYPE_BOOL: + return bool_type; default: /* Handle everything else */ return type; @@ -459,6 +304,8 @@ const glsl_type *glsl_type::get_scalar_type() const void _mesa_glsl_release_types(void) { + mtx_lock(&glsl_type::mutex); + if (glsl_type::array_types != NULL) { hash_table_dtor(glsl_type::array_types); glsl_type::array_types = NULL; @@ -468,6 +315,8 @@ _mesa_glsl_release_types(void) hash_table_dtor(glsl_type::record_types); glsl_type::record_types = NULL; } + + mtx_unlock(&glsl_type::mutex); } @@ -476,7 +325,7 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) : sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), sampler_type(0), interface_packing(0), vector_elements(0), matrix_columns(0), - name(NULL), length(length) + length(length), name(NULL) { this->fields.array = array; /* Inherit the gl type of the base. The GL type is used for @@ -490,17 +339,84 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) : * NUL. */ const unsigned name_length = strlen(array->name) + 10 + 3; + + mtx_lock(&glsl_type::mutex); char *const n = (char *) ralloc_size(this->mem_ctx, name_length); + mtx_unlock(&glsl_type::mutex); if (length == 0) snprintf(n, name_length, "%s[]", array->name); - else - snprintf(n, name_length, "%s[%u]", array->name, length); + else { + /* insert outermost dimensions in the correct spot + * otherwise the dimension order will be backwards + */ + const char *pos = strchr(array->name, '['); + if (pos) { + int idx = pos - array->name; + snprintf(n, idx+1, "%s", array->name); + snprintf(n + idx, name_length - idx, "[%u]%s", + length, array->name + idx); + } else { + snprintf(n, name_length, "%s[%u]", array->name, length); + } + } this->name = n; } +const glsl_type * +glsl_type::vec(unsigned components) +{ + if (components == 0 || components > 4) + return error_type; + + static const glsl_type *const ts[] = { + float_type, vec2_type, vec3_type, vec4_type + }; + return ts[components - 1]; +} + + +const glsl_type * +glsl_type::ivec(unsigned components) +{ + if (components == 0 || components > 4) + return error_type; + + static const glsl_type *const ts[] = { + int_type, ivec2_type, ivec3_type, ivec4_type + }; + return ts[components - 1]; +} + + +const glsl_type * +glsl_type::uvec(unsigned components) +{ + if (components == 0 || components > 4) + return error_type; + + static const glsl_type *const ts[] = { + uint_type, uvec2_type, uvec3_type, uvec4_type + }; + return ts[components - 1]; +} + + +const glsl_type * +glsl_type::bvec(unsigned components) +{ + if (components == 0 || components > 4) + return error_type; + + static const glsl_type *const ts[] = { + bool_type, bvec2_type, bvec3_type, bvec4_type + }; + return ts[components - 1]; +} + + const glsl_type * glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) { @@ -515,13 +431,13 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) if (columns == 1) { switch (base_type) { case GLSL_TYPE_UINT: - return uint_type + (rows - 1); + return uvec(rows); case GLSL_TYPE_INT: - return int_type + (rows - 1); + return ivec(rows); case GLSL_TYPE_FLOAT: - return float_type + (rows - 1); + return vec(rows); case GLSL_TYPE_BOOL: - return bool_type + (rows - 1); + return bvec(rows); default: return error_type; } @@ -562,12 +478,6 @@ 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 @@ -576,9 +486,19 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) char key[128]; snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size); + mtx_lock(&glsl_type::mutex); + + if (array_types == NULL) { + array_types = hash_table_ctor(64, hash_table_string_hash, + hash_table_string_compare); + } + const glsl_type *t = (glsl_type *) hash_table_find(array_types, key); + if (t == NULL) { + mtx_unlock(&glsl_type::mutex); t = new glsl_type(base, array_size); + mtx_lock(&glsl_type::mutex); hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); } @@ -587,10 +507,62 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) assert(t->length == array_size); assert(t->fields.array == base); + mtx_unlock(&glsl_type::mutex); + return t; } +bool +glsl_type::record_compare(const glsl_type *b) const +{ + if (this->length != b->length) + return false; + + if (this->interface_packing != b->interface_packing) + return false; + + /* From the GLSL 4.20 specification (Sec 4.2): + * + * "Structures must have the same name, sequence of type names, and + * type definitions, and field names to be considered the same type." + * + * GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5). + * + * Note that we cannot force type name check when comparing unnamed + * structure types, these have a unique name assigned during parsing. + */ + if (!this->is_anonymous() && !b->is_anonymous()) + if (strcmp(this->name, b->name) != 0) + return false; + + for (unsigned i = 0; i < this->length; i++) { + if (this->fields.structure[i].type != b->fields.structure[i].type) + return false; + if (strcmp(this->fields.structure[i].name, + b->fields.structure[i].name) != 0) + return false; + if (this->fields.structure[i].matrix_layout + != b->fields.structure[i].matrix_layout) + return false; + if (this->fields.structure[i].location + != b->fields.structure[i].location) + return false; + if (this->fields.structure[i].interpolation + != b->fields.structure[i].interpolation) + return false; + if (this->fields.structure[i].centroid + != b->fields.structure[i].centroid) + return false; + if (this->fields.structure[i].sample + != b->fields.structure[i].sample) + return false; + } + + return true; +} + + int glsl_type::record_key_compare(const void *a, const void *b) { @@ -603,24 +575,7 @@ glsl_type::record_key_compare(const void *a, const void *b) 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; + return !key1->record_compare(key2); } @@ -652,13 +607,17 @@ glsl_type::get_record_instance(const glsl_struct_field *fields, { const glsl_type key(fields, num_fields, name); + mtx_lock(&glsl_type::mutex); + 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(record_types, & key); if (t == NULL) { + mtx_unlock(&glsl_type::mutex); t = new glsl_type(fields, num_fields, name); + mtx_lock(&glsl_type::mutex); hash_table_insert(record_types, (void *) t, t); } @@ -667,6 +626,8 @@ glsl_type::get_record_instance(const glsl_struct_field *fields, assert(t->length == num_fields); assert(strcmp(t->name, name) == 0); + mtx_unlock(&glsl_type::mutex); + return t; } @@ -675,9 +636,11 @@ 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 char *block_name) { - const glsl_type key(fields, num_fields, packing, name); + const glsl_type key(fields, num_fields, packing, block_name); + + mtx_lock(&glsl_type::mutex); if (interface_types == NULL) { interface_types = hash_table_ctor(64, record_key_hash, record_key_compare); @@ -685,14 +648,18 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields, const glsl_type *t = (glsl_type *) hash_table_find(interface_types, & key); if (t == NULL) { - t = new glsl_type(fields, num_fields, packing, name); + mtx_unlock(&glsl_type::mutex); + t = new glsl_type(fields, num_fields, packing, block_name); + mtx_lock(&glsl_type::mutex); 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); + assert(strcmp(t->name, block_name) == 0); + + mtx_unlock(&glsl_type::mutex); return t; } @@ -753,7 +720,11 @@ glsl_type::component_slots() const case GLSL_TYPE_ARRAY: return this->length * this->fields.array->component_slots(); + case GLSL_TYPE_IMAGE: + return 1; + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: break; @@ -762,8 +733,35 @@ glsl_type::component_slots() const return 0; } +unsigned +glsl_type::uniform_locations() const +{ + unsigned size = 0; + + switch (this->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_BOOL: + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: + return 1; + + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: + for (unsigned i = 0; i < this->length; i++) + size += this->fields.structure[i].type->uniform_locations(); + return size; + case GLSL_TYPE_ARRAY: + return this->length * this->fields.array->uniform_locations(); + default: + return 0; + } +} + bool -glsl_type::can_implicitly_convert_to(const glsl_type *desired) const +glsl_type::can_implicitly_convert_to(const glsl_type *desired, + _mesa_glsl_parse_state *state) const { if (this == desired) return true; @@ -772,10 +770,23 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired) const if (this->matrix_columns > 1 || desired->matrix_columns > 1) return false; + /* Vector size must match. */ + if (this->vector_elements != desired->vector_elements) + return false; + /* int and uint can be converted to float. */ - return desired->is_float() - && this->is_integer() - && this->vector_elements == desired->vector_elements; + if (desired->is_float() && this->is_integer()) + return true; + + /* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint. + * Note that state may be NULL here, when resolving function calls in the + * linker. By this time, all the state-dependent checks have already + * happened though, so allow anything that's allowed in any shader version. */ + if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) && + desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT) + return true; + + return false; } unsigned @@ -873,9 +884,18 @@ glsl_type::std140_base_alignment(bool row_major) const if (this->is_record()) { unsigned base_alignment = 16; for (unsigned i = 0; i < this->length; i++) { + bool field_row_major = row_major; + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(this->fields.structure[i].matrix_layout); + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + field_row_major = true; + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { + field_row_major = false; + } + const struct glsl_type *field_type = this->fields.structure[i].type; base_alignment = MAX2(base_alignment, - field_type->std140_base_alignment(row_major)); + field_type->std140_base_alignment(field_row_major)); } return base_alignment; } @@ -919,8 +939,7 @@ glsl_type::std140_size(bool row_major) const * 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())) { + if (this->without_array()->is_matrix()) { const struct glsl_type *element_type; const struct glsl_type *vec_type; unsigned int array_len; @@ -982,17 +1001,122 @@ glsl_type::std140_size(bool row_major) const */ if (this->is_record()) { unsigned size = 0; + unsigned max_align = 0; + for (unsigned i = 0; i < this->length; i++) { + bool field_row_major = row_major; + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(this->fields.structure[i].matrix_layout); + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + field_row_major = true; + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { + field_row_major = false; + } + const struct glsl_type *field_type = this->fields.structure[i].type; - unsigned align = field_type->std140_base_alignment(row_major); + unsigned align = field_type->std140_base_alignment(field_row_major); size = glsl_align(size, align); - size += field_type->std140_size(row_major); + size += field_type->std140_size(field_row_major); + + max_align = MAX2(align, max_align); + + if (field_type->is_record() && (i + 1 < this->length)) + size = glsl_align(size, 16); } - size = glsl_align(size, - this->fields.structure[0].type->std140_base_alignment(row_major)); + size = glsl_align(size, MAX2(max_align, 16)); return size; } assert(!"not reached"); return -1; } + + +unsigned +glsl_type::count_attribute_slots() const +{ + /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: + * + * "A scalar input counts the same amount against this limit as a vec4, + * so applications may want to consider packing groups of four + * unrelated float inputs together into a vector to better utilize the + * capabilities of the underlying hardware. A matrix input will use up + * multiple locations. The number of locations used will equal the + * number of columns in the matrix." + * + * The spec does not explicitly say how arrays are counted. However, it + * should be safe to assume the total number of slots consumed by an array + * is the number of entries in the array multiplied by the number of slots + * consumed by a single element of the array. + * + * The spec says nothing about how structs are counted, because vertex + * attributes are not allowed to be (or contain) structs. However, Mesa + * allows varying structs, the number of varying slots taken up by a + * varying struct is simply equal to the sum of the number of slots taken + * up by each element. + */ + switch (this->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_BOOL: + return this->matrix_columns; + + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: { + unsigned size = 0; + + for (unsigned i = 0; i < this->length; i++) + size += this->fields.structure[i].type->count_attribute_slots(); + + return size; + } + + case GLSL_TYPE_ARRAY: + return this->length * this->fields.array->count_attribute_slots(); + + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: + case GLSL_TYPE_ATOMIC_UINT: + case GLSL_TYPE_VOID: + case GLSL_TYPE_ERROR: + break; + } + + assert(!"Unexpected type in count_attribute_slots()"); + + return 0; +} + +int +glsl_type::coordinate_components() const +{ + int size; + + switch (sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: + case GLSL_SAMPLER_DIM_BUF: + size = 1; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_MS: + case GLSL_SAMPLER_DIM_EXTERNAL: + size = 2; + break; + case GLSL_SAMPLER_DIM_3D: + case GLSL_SAMPLER_DIM_CUBE: + size = 3; + break; + default: + assert(!"Should not get here."); + size = 1; + break; + } + + /* Array textures need an additional component for the array index. */ + if (sampler_array) + size += 1; + + return size; +}