X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=inline;f=src%2Fglsl%2Fglsl_types.cpp;h=8510671d2f32c7d096830200150153a0fae58bdc;hb=57f24299b7fe0f7b20c2a3cf1e94c747825b568d;hp=3c13fcea550998427bcff3b40aa09fbcd71ad655;hpb=1cb81d3a9b65781802f641fb3e4435edfed7f14a;p=mesa.git diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 3c13fcea550..8510671d2f3 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -25,13 +25,14 @@ #include "main/core.h" /* for Elements, MAX2 */ #include "glsl_parser_extras.h" #include "glsl_types.h" -extern "C" { -#include "program/hash_table.h" -} +#include "util/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; +hash_table *glsl_type::subroutine_types = NULL; void *glsl_type::mem_ctx = NULL; void @@ -53,9 +54,14 @@ 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)); @@ -71,9 +77,14 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, sampler_array(array), sampler_type(type), interface_packing(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) { @@ -95,11 +106,14 @@ 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, @@ -109,7 +123,10 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, 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; + this->fields.structure[i].patch = fields[i].patch; } + + mtx_unlock(&glsl_type::mutex); } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -123,6 +140,8 @@ 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); @@ -137,9 +156,28 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, 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; + this->fields.structure[i].patch = fields[i].patch; } + + 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 @@ -174,6 +212,22 @@ glsl_type::contains_integer() const } } +bool +glsl_type::contains_double() const +{ + if (this->is_array()) { + return this->fields.array->contains_double(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_double()) + return true; + } + return false; + } else { + return this->is_double(); + } +} + bool glsl_type::contains_opaque() const { switch (base_type) { @@ -182,7 +236,7 @@ glsl_type::contains_opaque() const { case GLSL_TYPE_ATOMIC_UINT: return true; case GLSL_TYPE_ARRAY: - return element_type()->contains_opaque(); + return fields.array->contains_opaque(); case GLSL_TYPE_STRUCT: for (unsigned int i = 0; i < length; i++) { if (fields.structure[i].type->contains_opaque()) @@ -194,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 { @@ -249,6 +319,8 @@ const glsl_type *glsl_type::get_base_type() const return int_type; case GLSL_TYPE_FLOAT: return float_type; + case GLSL_TYPE_DOUBLE: + return double_type; case GLSL_TYPE_BOOL: return bool_type; default: @@ -273,6 +345,8 @@ const glsl_type *glsl_type::get_scalar_type() const return int_type; case GLSL_TYPE_FLOAT: return float_type; + case GLSL_TYPE_DOUBLE: + return double_type; case GLSL_TYPE_BOOL: return bool_type; default: @@ -285,15 +359,24 @@ const glsl_type *glsl_type::get_scalar_type() const void _mesa_glsl_release_types(void) { + /* Should only be called during atexit (either when unloading shared + * object, or if process terminates), so no mutex-locking should be + * necessary. + */ if (glsl_type::array_types != NULL) { - hash_table_dtor(glsl_type::array_types); + _mesa_hash_table_destroy(glsl_type::array_types, NULL); glsl_type::array_types = NULL; } if (glsl_type::record_types != NULL) { - hash_table_dtor(glsl_type::record_types); + _mesa_hash_table_destroy(glsl_type::record_types, NULL); glsl_type::record_types = NULL; } + + if (glsl_type::interface_types != NULL) { + _mesa_hash_table_destroy(glsl_type::interface_types, NULL); + glsl_type::interface_types = NULL; + } } @@ -302,7 +385,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 @@ -316,7 +399,10 @@ 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); @@ -351,6 +437,17 @@ glsl_type::vec(unsigned components) return ts[components - 1]; } +const glsl_type * +glsl_type::dvec(unsigned components) +{ + if (components == 0 || components > 4) + return error_type; + + static const glsl_type *const ts[] = { + double_type, dvec2_type, dvec3_type, dvec4_type + }; + return ts[components - 1]; +} const glsl_type * glsl_type::ivec(unsigned components) @@ -410,13 +507,15 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) return ivec(rows); case GLSL_TYPE_FLOAT: return vec(rows); + case GLSL_TYPE_DOUBLE: + return dvec(rows); case GLSL_TYPE_BOOL: return bvec(rows); default: return error_type; } } else { - if ((base_type != GLSL_TYPE_FLOAT) || (rows == 1)) + if ((base_type != GLSL_TYPE_FLOAT && base_type != GLSL_TYPE_DOUBLE) || (rows == 1)) return error_type; /* GLSL matrix types are named mat{COLUMNS}x{ROWS}. Only the following @@ -430,17 +529,32 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) */ #define IDX(c,r) (((c-1)*3) + (r-1)) - switch (IDX(columns, rows)) { - case IDX(2,2): return mat2_type; - case IDX(2,3): return mat2x3_type; - case IDX(2,4): return mat2x4_type; - case IDX(3,2): return mat3x2_type; - case IDX(3,3): return mat3_type; - case IDX(3,4): return mat3x4_type; - case IDX(4,2): return mat4x2_type; - case IDX(4,3): return mat4x3_type; - case IDX(4,4): return mat4_type; - default: return error_type; + if (base_type == GLSL_TYPE_DOUBLE) { + switch (IDX(columns, rows)) { + case IDX(2,2): return dmat2_type; + case IDX(2,3): return dmat2x3_type; + case IDX(2,4): return dmat2x4_type; + case IDX(3,2): return dmat3x2_type; + case IDX(3,3): return dmat3_type; + case IDX(3,4): return dmat3x4_type; + case IDX(4,2): return dmat4x2_type; + case IDX(4,3): return dmat4x3_type; + case IDX(4,4): return dmat4_type; + default: return error_type; + } + } else { + switch (IDX(columns, rows)) { + case IDX(2,2): return mat2_type; + case IDX(2,3): return mat2x3_type; + case IDX(2,4): return mat2x4_type; + case IDX(3,2): return mat3x2_type; + case IDX(3,3): return mat3_type; + case IDX(3,4): return mat3x4_type; + case IDX(4,2): return mat4x2_type; + case IDX(4,3): return mat4x3_type; + case IDX(4,4): return mat4_type; + default: return error_type; + } } } @@ -448,16 +562,121 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) return error_type; } - const glsl_type * -glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) +glsl_type::get_sampler_instance(enum glsl_sampler_dim dim, + bool shadow, + bool array, + glsl_base_type type) { - - if (array_types == NULL) { - array_types = hash_table_ctor(64, hash_table_string_hash, - hash_table_string_compare); + switch (type) { + case GLSL_TYPE_FLOAT: + switch (dim) { + case GLSL_SAMPLER_DIM_1D: + if (shadow) + return (array ? sampler1DArrayShadow_type : sampler1DShadow_type); + else + return (array ? sampler1DArray_type : sampler1D_type); + case GLSL_SAMPLER_DIM_2D: + if (shadow) + return (array ? sampler2DArrayShadow_type : sampler2DShadow_type); + else + return (array ? sampler2DArray_type : sampler2D_type); + case GLSL_SAMPLER_DIM_3D: + if (shadow || array) + return error_type; + else + return sampler3D_type; + case GLSL_SAMPLER_DIM_CUBE: + if (shadow) + return (array ? samplerCubeArrayShadow_type : samplerCubeShadow_type); + else + return (array ? samplerCubeArray_type : samplerCube_type); + case GLSL_SAMPLER_DIM_RECT: + if (array) + return error_type; + if (shadow) + return sampler2DRectShadow_type; + else + return sampler2DRect_type; + case GLSL_SAMPLER_DIM_BUF: + if (shadow || array) + return error_type; + else + return samplerBuffer_type; + case GLSL_SAMPLER_DIM_MS: + if (shadow) + return error_type; + return (array ? sampler2DMSArray_type : sampler2DMS_type); + case GLSL_SAMPLER_DIM_EXTERNAL: + if (shadow || array) + return error_type; + else + return samplerExternalOES_type; + } + case GLSL_TYPE_INT: + if (shadow) + return error_type; + switch (dim) { + case GLSL_SAMPLER_DIM_1D: + return (array ? isampler1DArray_type : isampler1D_type); + case GLSL_SAMPLER_DIM_2D: + return (array ? isampler2DArray_type : isampler2D_type); + case GLSL_SAMPLER_DIM_3D: + if (array) + return error_type; + return isampler3D_type; + case GLSL_SAMPLER_DIM_CUBE: + return (array ? isamplerCubeArray_type : isamplerCube_type); + case GLSL_SAMPLER_DIM_RECT: + if (array) + return error_type; + return isampler2DRect_type; + case GLSL_SAMPLER_DIM_BUF: + if (array) + return error_type; + return isamplerBuffer_type; + case GLSL_SAMPLER_DIM_MS: + return (array ? isampler2DMSArray_type : isampler2DMS_type); + case GLSL_SAMPLER_DIM_EXTERNAL: + return error_type; + } + case GLSL_TYPE_UINT: + if (shadow) + return error_type; + switch (dim) { + case GLSL_SAMPLER_DIM_1D: + return (array ? usampler1DArray_type : usampler1D_type); + case GLSL_SAMPLER_DIM_2D: + return (array ? usampler2DArray_type : usampler2D_type); + case GLSL_SAMPLER_DIM_3D: + if (array) + return error_type; + return usampler3D_type; + case GLSL_SAMPLER_DIM_CUBE: + return (array ? usamplerCubeArray_type : usamplerCube_type); + case GLSL_SAMPLER_DIM_RECT: + if (array) + return error_type; + return usampler2DRect_type; + case GLSL_SAMPLER_DIM_BUF: + if (array) + return error_type; + return usamplerBuffer_type; + case GLSL_SAMPLER_DIM_MS: + return (array ? usampler2DMSArray_type : usampler2DMS_type); + case GLSL_SAMPLER_DIM_EXTERNAL: + return error_type; + } + default: + return error_type; } + unreachable("switch statement above should be complete"); +} + +const glsl_type * +glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) +{ /* 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 @@ -466,18 +685,31 @@ 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); - const glsl_type *t = (glsl_type *) hash_table_find(array_types, key); - if (t == NULL) { - t = new glsl_type(base, array_size); + mtx_lock(&glsl_type::mutex); + + if (array_types == NULL) { + array_types = _mesa_hash_table_create(NULL, _mesa_key_hash_string, + _mesa_key_string_equal); + } + + const struct hash_entry *entry = _mesa_hash_table_search(array_types, key); + if (entry == NULL) { + mtx_unlock(&glsl_type::mutex); + const glsl_type *t = new glsl_type(base, array_size); + mtx_lock(&glsl_type::mutex); - hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); + entry = _mesa_hash_table_insert(array_types, + ralloc_strdup(mem_ctx, key), + (void *) t); } - assert(t->base_type == GLSL_TYPE_ARRAY); - assert(t->length == array_size); - assert(t->fields.array == base); + assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_ARRAY); + assert(((glsl_type *) entry->data)->length == array_size); + assert(((glsl_type *) entry->data)->fields.array == base); + + mtx_unlock(&glsl_type::mutex); - return t; + return (glsl_type *) entry->data; } @@ -490,6 +722,20 @@ glsl_type::record_compare(const glsl_type *b) const 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; @@ -511,46 +757,46 @@ glsl_type::record_compare(const glsl_type *b) const if (this->fields.structure[i].sample != b->fields.structure[i].sample) return false; + if (this->fields.structure[i].patch + != b->fields.structure[i].patch) + return false; } return true; } -int +bool 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; - /* Return zero is the types match (there is zero difference) or non-zero - * otherwise. - */ - if (strcmp(key1->name, key2->name) != 0) - return 1; - - return !key1->record_compare(key2); + return strcmp(key1->name, key2->name) == 0 && key1->record_compare(key2); } +/** + * Generate an integer hash value for a glsl_type structure type. + */ unsigned 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); + uintptr_t hash = key->length; + unsigned retval; 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); + /* casting pointer to uintptr_t */ + hash = (hash * 13 ) + (uintptr_t) key->fields.structure[i].type; } - return hash_table_string_hash(& hash_key); + if (sizeof(hash) == 8) + retval = (hash & 0xffffffff) ^ ((uint64_t) hash >> 32); + else + retval = hash; + + return retval; } @@ -561,22 +807,30 @@ 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); + record_types = _mesa_hash_table_create(NULL, record_key_hash, + record_key_compare); } - const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key); - if (t == NULL) { - t = new glsl_type(fields, num_fields, name); + const struct hash_entry *entry = _mesa_hash_table_search(record_types, + &key); + if (entry == NULL) { + mtx_unlock(&glsl_type::mutex); + const glsl_type *t = new glsl_type(fields, num_fields, name); + mtx_lock(&glsl_type::mutex); - hash_table_insert(record_types, (void *) t, t); + entry = _mesa_hash_table_insert(record_types, t, (void *) t); } - assert(t->base_type == GLSL_TYPE_STRUCT); - assert(t->length == num_fields); - assert(strcmp(t->name, name) == 0); + assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_STRUCT); + assert(((glsl_type *) entry->data)->length == num_fields); + assert(strcmp(((glsl_type *) entry->data)->name, name) == 0); - return t; + mtx_unlock(&glsl_type::mutex); + + return (glsl_type *) entry->data; } @@ -588,22 +842,128 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields, { 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); + interface_types = _mesa_hash_table_create(NULL, 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, block_name); + const struct hash_entry *entry = _mesa_hash_table_search(interface_types, + &key); + if (entry == NULL) { + mtx_unlock(&glsl_type::mutex); + const glsl_type *t = new glsl_type(fields, num_fields, + packing, block_name); + mtx_lock(&glsl_type::mutex); - hash_table_insert(interface_types, (void *) t, t); + entry = _mesa_hash_table_insert(interface_types, t, (void *) t); } - assert(t->base_type == GLSL_TYPE_INTERFACE); - assert(t->length == num_fields); - assert(strcmp(t->name, block_name) == 0); + assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_INTERFACE); + assert(((glsl_type *) entry->data)->length == num_fields); + assert(strcmp(((glsl_type *) entry->data)->name, block_name) == 0); - return t; + mtx_unlock(&glsl_type::mutex); + + 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) +{ + if (type_a == type_b) { + return type_a; + } else if (type_a->is_matrix() && type_b->is_matrix()) { + /* Matrix multiply. The columns of A must match the rows of B. Given + * the other previously tested constraints, this means the vector type + * of a row from A must be the same as the vector type of a column from + * B. + */ + if (type_a->row_type() == type_b->column_type()) { + /* The resulting matrix has the number of columns of matrix B and + * the number of rows of matrix A. We get the row count of A by + * looking at the size of a vector that makes up a column. The + * transpose (size of a row) is done for B. + */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + type_b->row_type()->vector_elements); + assert(type != error_type); + + return type; + } + } else if (type_a->is_matrix()) { + /* A is a matrix and B is a column vector. Columns of A must match + * rows of B. Given the other previously tested constraints, this + * means the vector type of a row from A must be the same as the + * vector the type of B. + */ + if (type_a->row_type() == type_b) { + /* The resulting vector has a number of elements equal to + * the number of rows of matrix A. */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + 1); + assert(type != error_type); + + return type; + } + } else { + assert(type_b->is_matrix()); + + /* A is a row vector and B is a matrix. Columns of A must match rows + * of B. Given the other previously tested constraints, this means + * the type of A must be the same as the vector type of a column from + * B. + */ + if (type_a == type_b->column_type()) { + /* The resulting vector has a number of elements equal to + * the number of columns of matrix B. */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_b->row_type()->vector_elements, + 1); + assert(type != error_type); + + return type; + } + } + + return error_type; } @@ -649,6 +1009,9 @@ glsl_type::component_slots() const case GLSL_TYPE_BOOL: return this->components(); + case GLSL_TYPE_DOUBLE: + return 2 * this->components(); + case GLSL_TYPE_STRUCT: case GLSL_TYPE_INTERFACE: { unsigned size = 0; @@ -668,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; } @@ -684,9 +1048,11 @@ glsl_type::uniform_locations() const case GLSL_TYPE_UINT: case GLSL_TYPE_INT: case GLSL_TYPE_FLOAT: + case GLSL_TYPE_DOUBLE: case GLSL_TYPE_BOOL: case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: + case GLSL_TYPE_SUBROUTINE: return 1; case GLSL_TYPE_STRUCT: @@ -728,12 +1094,26 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired, desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT) return true; + /* No implicit conversions from double. */ + if ((!state || state->has_double()) && this->is_double()) + return false; + + /* Conversions from different types to double. */ + if ((!state || state->has_double()) && desired->is_double()) { + if (this->is_float()) + return true; + if (this->is_integer()) + return true; + } + return false; } unsigned glsl_type::std140_base_alignment(bool row_major) const { + unsigned N = is_double() ? 8 : 4; + /* (1) If the member is a scalar consuming basic machine units, the * base alignment is . * @@ -747,12 +1127,12 @@ glsl_type::std140_base_alignment(bool row_major) const if (this->is_scalar() || this->is_vector()) { switch (this->vector_elements) { case 1: - return 4; + return N; case 2: - return 8; + return 2 * N; case 3: case 4: - return 16; + return 4 * N; } } @@ -781,7 +1161,8 @@ glsl_type::std140_base_alignment(bool row_major) const this->fields.array->is_matrix()) { return MAX2(this->fields.array->std140_base_alignment(row_major), 16); } else { - assert(this->fields.array->is_record()); + assert(this->fields.array->is_record() || + this->fields.array->is_array()); return this->fields.array->std140_base_alignment(row_major); } } @@ -801,10 +1182,10 @@ glsl_type::std140_base_alignment(bool row_major) const int r = this->vector_elements; if (row_major) { - vec_type = get_instance(GLSL_TYPE_FLOAT, c, 1); + vec_type = get_instance(base_type, c, 1); array_type = glsl_type::get_array_instance(vec_type, r); } else { - vec_type = get_instance(GLSL_TYPE_FLOAT, r, 1); + vec_type = get_instance(base_type, r, 1); array_type = glsl_type::get_array_instance(vec_type, c); } @@ -849,6 +1230,8 @@ glsl_type::std140_base_alignment(bool row_major) const unsigned glsl_type::std140_size(bool row_major) const { + unsigned N = is_double() ? 8 : 4; + /* (1) If the member is a scalar consuming basic machine units, the * base alignment is . * @@ -860,7 +1243,7 @@ glsl_type::std140_size(bool row_major) const * basic machine units, the base alignment is 4. */ if (this->is_scalar() || this->is_vector()) { - return this->vector_elements * 4; + return this->vector_elements * N; } /* (5) If the member is a column-major matrix with columns and @@ -895,11 +1278,12 @@ glsl_type::std140_size(bool row_major) const } if (row_major) { - vec_type = get_instance(GLSL_TYPE_FLOAT, - element_type->matrix_columns, 1); + vec_type = get_instance(element_type->base_type, + element_type->matrix_columns, 1); + array_len *= element_type->vector_elements; } else { - vec_type = get_instance(GLSL_TYPE_FLOAT, + vec_type = get_instance(element_type->base_type, element_type->vector_elements, 1); array_len *= element_type->matrix_columns; } @@ -965,7 +1349,7 @@ glsl_type::std140_size(bool row_major) const if (field_type->is_record() && (i + 1 < this->length)) size = glsl_align(size, 16); } - size = glsl_align(size, max_align); + size = glsl_align(size, MAX2(max_align, 16)); return size; } @@ -1002,6 +1386,7 @@ glsl_type::count_attribute_slots() const case GLSL_TYPE_INT: case GLSL_TYPE_FLOAT: case GLSL_TYPE_BOOL: + case GLSL_TYPE_DOUBLE: return this->matrix_columns; case GLSL_TYPE_STRUCT: @@ -1021,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; } @@ -1056,8 +1442,13 @@ glsl_type::coordinate_components() const break; } - /* Array textures need an additional component for the array index. */ - if (sampler_array) + /* Array textures need an additional component for the array index, except + * for cubemap array images that behave like a 2D array of interleaved + * cubemap faces. + */ + if (sampler_array && + !(base_type == GLSL_TYPE_IMAGE && + sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE)) size += 1; return size;