diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index 1aeb4439544..288ddcf5dea 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/glsl_types.cpp @@ -46,13 +46,15 @@ static uint32_t glsl_type_users = 0; glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, unsigned vector_elements, unsigned matrix_columns, const char *name, - unsigned explicit_stride, bool row_major) : + unsigned explicit_stride, bool row_major, + unsigned explicit_alignment) : gl_type(gl_type), base_type(base_type), sampled_type(GLSL_TYPE_VOID), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), interface_packing(0), interface_row_major(row_major), packed(0), vector_elements(vector_elements), matrix_columns(matrix_columns), - length(0), explicit_stride(explicit_stride) + length(0), explicit_stride(explicit_stride), + explicit_alignment(explicit_alignment) { /* Values of these types must fit in the two bits of * glsl_type::sampled_type. @@ -75,6 +77,7 @@ glsl_type::glsl_type(GLenum gl_type, /* Neither dimension is zero or both dimensions are zero. */ assert((vector_elements == 0) == (matrix_columns == 0)); + assert(util_is_power_of_two_or_zero(explicit_alignment)); memset(& fields, 0, sizeof(fields)); } @@ -86,7 +89,7 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, sampler_dimensionality(dim), sampler_shadow(shadow), sampler_array(array), interface_packing(0), interface_row_major(0), packed(0), - length(0), explicit_stride(0) + length(0), explicit_stride(0), explicit_alignment(0) { this->mem_ctx = ralloc_context(NULL); assert(this->mem_ctx != NULL); @@ -100,16 +103,20 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, - const char *name, bool packed) : + const char *name, bool packed, + unsigned explicit_alignment) : gl_type(0), base_type(GLSL_TYPE_STRUCT), sampled_type(GLSL_TYPE_VOID), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), interface_packing(0), interface_row_major(0), packed(packed), vector_elements(0), matrix_columns(0), - length(num_fields), explicit_stride(0) + length(num_fields), explicit_stride(0), + explicit_alignment(explicit_alignment) { unsigned int i; + assert(util_is_power_of_two_or_zero(explicit_alignment)); + this->mem_ctx = ralloc_context(NULL); assert(this->mem_ctx != NULL); @@ -136,7 +143,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, interface_packing((unsigned) packing), interface_row_major((unsigned) row_major), packed(0), vector_elements(0), matrix_columns(0), - length(num_fields), explicit_stride(0) + length(num_fields), explicit_stride(0), explicit_alignment(0) { unsigned int i; @@ -161,7 +168,7 @@ glsl_type::glsl_type(const glsl_type *return_type, sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), interface_packing(0), interface_row_major(0), packed(0), vector_elements(0), matrix_columns(0), - length(num_params), explicit_stride(0) + length(num_params), explicit_stride(0), explicit_alignment(0) { unsigned int i; @@ -190,7 +197,7 @@ glsl_type::glsl_type(const char *subroutine_name) : sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), interface_packing(0), interface_row_major(0), packed(0), vector_elements(1), matrix_columns(1), - length(0), explicit_stride(0) + length(0), explicit_stride(0), explicit_alignment(0) { this->mem_ctx = ralloc_context(NULL); assert(this->mem_ctx != NULL); @@ -567,7 +574,8 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length, sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), interface_packing(0), interface_row_major(0), packed(0), vector_elements(0), matrix_columns(0), - length(length), name(NULL), explicit_stride(explicit_stride) + length(length), name(NULL), explicit_stride(explicit_stride), + explicit_alignment(array->explicit_alignment) { this->fields.array = array; /* Inherit the gl type of the base. The GL type is used for @@ -650,24 +658,30 @@ VECN(components, uint8_t, u8vec) const glsl_type * glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns, - unsigned explicit_stride, bool row_major) + unsigned explicit_stride, bool row_major, + unsigned explicit_alignment) { if (base_type == GLSL_TYPE_VOID) { - assert(explicit_stride == 0 && !row_major); + assert(explicit_stride == 0 && explicit_alignment == 0 && !row_major); return void_type; } - /* Matrix and vector types with explicit strides have to be looked up in a - * table so they're handled separately. + /* Matrix and vector types with explicit strides or alignment have to be + * looked up in a table so they're handled separately. */ - if (explicit_stride > 0) { + if (explicit_stride > 0 || explicit_alignment > 0) { + if (explicit_alignment > 0) { + assert(util_is_power_of_two_nonzero(explicit_alignment)); + assert(explicit_stride % explicit_alignment == 0); + } + const glsl_type *bare_type = get_instance(base_type, rows, columns); - assert(columns > 1 || !row_major); + assert(columns > 1 || (rows > 1 && !row_major)); char name[128]; - snprintf(name, sizeof(name), "%sx%uB%s", bare_type->name, - explicit_stride, row_major ? "RM" : ""); + snprintf(name, sizeof(name), "%sx%ua%uB%s", bare_type->name, + explicit_stride, explicit_alignment, row_major ? "RM" : ""); mtx_lock(&glsl_type::hash_mutex); assert(glsl_type_users > 0); @@ -684,7 +698,8 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns, const glsl_type *t = new glsl_type(bare_type->gl_type, (glsl_base_type)base_type, rows, columns, name, - explicit_stride, row_major); + explicit_stride, row_major, + explicit_alignment); entry = _mesa_hash_table_insert(explicit_matrix_types, t->name, (void *)t); @@ -694,6 +709,7 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns, assert(((glsl_type *) entry->data)->vector_elements == rows); assert(((glsl_type *) entry->data)->matrix_columns == columns); assert(((glsl_type *) entry->data)->explicit_stride == explicit_stride); + assert(((glsl_type *) entry->data)->explicit_alignment == explicit_alignment); const glsl_type *t = (const glsl_type *) entry->data; @@ -1124,6 +1140,9 @@ glsl_type::record_compare(const glsl_type *b, bool match_name, if (this->interface_row_major != b->interface_row_major) return false; + if (this->explicit_alignment != b->explicit_alignment) + return false; + /* From the GLSL 4.20 specification (Sec 4.2): * * "Structures must have the same name, sequence of type names, and @@ -1251,9 +1270,9 @@ const glsl_type * glsl_type::get_struct_instance(const glsl_struct_field *fields, unsigned num_fields, const char *name, - bool packed) + bool packed, unsigned explicit_alignment) { - const glsl_type key(fields, num_fields, name, packed); + const glsl_type key(fields, num_fields, name, packed, explicit_alignment); mtx_lock(&glsl_type::hash_mutex); assert(glsl_type_users > 0); @@ -1266,7 +1285,8 @@ glsl_type::get_struct_instance(const glsl_struct_field *fields, const struct hash_entry *entry = _mesa_hash_table_search(struct_types, &key); if (entry == NULL) { - const glsl_type *t = new glsl_type(fields, num_fields, name, packed); + const glsl_type *t = new glsl_type(fields, num_fields, name, packed, + explicit_alignment); entry = _mesa_hash_table_insert(struct_types, t, (void *) t); } @@ -1275,6 +1295,7 @@ glsl_type::get_struct_instance(const glsl_struct_field *fields, assert(((glsl_type *) entry->data)->length == num_fields); assert(strcmp(((glsl_type *) entry->data)->name, name) == 0); assert(((glsl_type *) entry->data)->packed == packed); + assert(((glsl_type *) entry->data)->explicit_alignment == explicit_alignment); glsl_type *t = (glsl_type *) entry->data; @@ -2448,9 +2469,16 @@ const glsl_type * glsl_type::get_explicit_type_for_size_align(glsl_type_size_align_func type_info, unsigned *size, unsigned *alignment) const { - if (this->is_scalar() || this->is_vector()) { + if (this->is_scalar()) { type_info(this, size, alignment); + assert(*size == explicit_type_scalar_byte_size(this)); + assert(*alignment == explicit_type_scalar_byte_size(this)); return this; + } else if (this->is_vector()) { + type_info(this, size, alignment); + assert(*alignment % explicit_type_scalar_byte_size(this) == 0); + return glsl_type::get_instance(this->base_type, this->vector_elements, + 1, 0, false, *alignment); } else if (this->is_array()) { unsigned elem_size, elem_align; const struct glsl_type *explicit_element = @@ -2484,7 +2512,7 @@ glsl_type::get_explicit_type_for_size_align(glsl_type_size_align_func type_info, const glsl_type *type; if (this->is_struct()) { type = get_struct_instance(fields, this->length, this->name, - this->packed); + this->packed, *alignment); } else { assert(!this->packed); type = get_interface_instance(fields, this->length, @@ -2500,9 +2528,10 @@ glsl_type::get_explicit_type_for_size_align(glsl_type_size_align_func type_info, unsigned stride = align(col_size, col_align); *size = this->matrix_columns * stride; + /* Matrix and column alignments match. See glsl_type::column_type() */ *alignment = col_align; return glsl_type::get_instance(this->base_type, this->vector_elements, - this->matrix_columns, stride, false); + this->matrix_columns, stride, false, *alignment); } else { unreachable("Unhandled type."); } @@ -2684,7 +2713,8 @@ union packed_type { unsigned interface_row_major:1; unsigned vector_elements:3; unsigned matrix_columns:3; - unsigned explicit_stride:20; + unsigned explicit_stride:16; + unsigned explicit_alignment:4; } basic; struct { unsigned base_type:5; @@ -2703,7 +2733,8 @@ union packed_type { unsigned base_type:5; unsigned interface_packing_or_packed:2; unsigned interface_row_major:1; - unsigned length:24; + unsigned length:20; + unsigned explicit_alignment:4; } strct; }; @@ -2768,13 +2799,17 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type) else if (type->vector_elements == 16) encoded.basic.vector_elements = 6; encoded.basic.matrix_columns = type->matrix_columns; - encoded.basic.explicit_stride = MIN2(type->explicit_stride, 0xfffff); + encoded.basic.explicit_stride = MIN2(type->explicit_stride, 0xffff); + encoded.basic.explicit_alignment = + MIN2(ffs(type->explicit_alignment), 0xf); blob_write_uint32(blob, encoded.u32); /* If we don't have enough bits for explicit_stride, store it * separately. */ - if (encoded.basic.explicit_stride == 0xfffff) + if (encoded.basic.explicit_stride == 0xffff) blob_write_uint32(blob, type->explicit_stride); + if (encoded.basic.explicit_alignment == 0xf) + blob_write_uint32(blob, type->explicit_alignment); return; case GLSL_TYPE_SAMPLER: encoded.sampler.dimensionality = type->sampler_dimensionality; @@ -2808,7 +2843,9 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type) return; case GLSL_TYPE_STRUCT: case GLSL_TYPE_INTERFACE: - encoded.strct.length = MIN2(type->length, 0xffffff); + encoded.strct.length = MIN2(type->length, 0xfffff); + encoded.strct.explicit_alignment = + MIN2(ffs(type->explicit_alignment), 0xf); if (type->is_interface()) { encoded.strct.interface_packing_or_packed = type->interface_packing; encoded.strct.interface_row_major = type->interface_row_major; @@ -2819,8 +2856,10 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type) blob_write_string(blob, type->name); /* If we don't have enough bits for length, store it separately. */ - if (encoded.strct.length == 0xffffff) + if (encoded.strct.length == 0xfffff) blob_write_uint32(blob, type->length); + if (encoded.strct.length == 0xf) + blob_write_uint32(blob, type->explicit_alignment); for (unsigned i = 0; i < type->length; i++) encode_glsl_struct_field(blob, &type->fields.structure[i]); @@ -2863,8 +2902,13 @@ decode_type_from_blob(struct blob_reader *blob) case GLSL_TYPE_INT64: case GLSL_TYPE_BOOL: { unsigned explicit_stride = encoded.basic.explicit_stride; - if (explicit_stride == 0xfffff) + if (explicit_stride == 0xffff) explicit_stride = blob_read_uint32(blob); + unsigned explicit_alignment = encoded.basic.explicit_alignment; + if (explicit_alignment == 0xf) + explicit_alignment = blob_read_uint32(blob); + else if (explicit_alignment > 0) + explicit_alignment = 1 << (explicit_alignment - 1); uint32_t vector_elements = encoded.basic.vector_elements; if (vector_elements == 5) vector_elements = 8; @@ -2873,7 +2917,8 @@ decode_type_from_blob(struct blob_reader *blob) return glsl_type::get_instance(base_type, encoded.basic.vector_elements, encoded.basic.matrix_columns, explicit_stride, - encoded.basic.interface_row_major); + encoded.basic.interface_row_major, + explicit_alignment); } case GLSL_TYPE_SAMPLER: return glsl_type::get_sampler_instance((enum glsl_sampler_dim)encoded.sampler.dimensionality, @@ -2902,8 +2947,13 @@ decode_type_from_blob(struct blob_reader *blob) case GLSL_TYPE_INTERFACE: { char *name = blob_read_string(blob); unsigned num_fields = encoded.strct.length; - if (num_fields == 0xffffff) + if (num_fields == 0xfffff) num_fields = blob_read_uint32(blob); + unsigned explicit_alignment = encoded.strct.explicit_alignment; + if (explicit_alignment == 0xf) + explicit_alignment = blob_read_uint32(blob); + else if (explicit_alignment > 0) + explicit_alignment = 1 << (explicit_alignment - 1); glsl_struct_field *fields = (glsl_struct_field *) malloc(sizeof(glsl_struct_field) * num_fields); @@ -2912,6 +2962,7 @@ decode_type_from_blob(struct blob_reader *blob) const glsl_type *t; if (base_type == GLSL_TYPE_INTERFACE) { + assert(explicit_alignment == 0); enum glsl_interface_packing packing = (glsl_interface_packing) encoded.strct.interface_packing_or_packed; bool row_major = encoded.strct.interface_row_major; @@ -2919,7 +2970,8 @@ decode_type_from_blob(struct blob_reader *blob) row_major, name); } else { unsigned packed = encoded.strct.interface_packing_or_packed; - t = glsl_type::get_struct_instance(fields, num_fields, name, packed); + t = glsl_type::get_struct_instance(fields, num_fields, name, packed, + explicit_alignment); } free(fields); diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index 6a57c7026a6..8058425e0d0 100644 --- a/src/compiler/glsl_types.h +++ b/src/compiler/glsl_types.h @@ -332,6 +332,13 @@ public: */ unsigned explicit_stride; + /** + * Explicit alignment. This is used to communicate explicit alignment + * constraints. Should be 0 if the type has no explicit alignment + * constraint. + */ + unsigned explicit_alignment; + /** * Subtype of composite data types. */ @@ -420,7 +427,8 @@ public: static const glsl_type *get_instance(unsigned base_type, unsigned rows, unsigned columns, unsigned explicit_stride = 0, - bool row_major = false); + bool row_major = false, + unsigned explicit_alignment = 0); /** * Get the instance of a sampler type @@ -446,7 +454,8 @@ public: static const glsl_type *get_struct_instance(const glsl_struct_field *fields, unsigned num_fields, const char *name, - bool packed = false); + bool packed = false, + unsigned explicit_alignment = 0); /** * Get the instance of an interface block type @@ -1107,10 +1116,21 @@ public: if (!is_matrix()) return error_type; - if (explicit_stride && interface_row_major) - return get_instance(base_type, vector_elements, 1, explicit_stride); - else - return get_instance(base_type, vector_elements, 1); + if (interface_row_major) { + /* If we're row-major, the vector element stride is the same as the + * matrix stride and we have no alignment (i.e. component-aligned). + */ + return get_instance(base_type, vector_elements, 1, + explicit_stride, false, 0); + } else { + /* Otherwise, the vector is tightly packed (stride=0). For + * alignment, we treat a matrix as an array of columns make the same + * assumption that the alignment of the column is the same as the + * alignment of the whole matrix. + */ + return get_instance(base_type, vector_elements, 1, + 0, false, explicit_alignment); + } } /** @@ -1236,7 +1256,8 @@ private: glsl_type(GLenum gl_type, glsl_base_type base_type, unsigned vector_elements, unsigned matrix_columns, const char *name, - unsigned explicit_stride = 0, bool row_major = false); + unsigned explicit_stride = 0, bool row_major = false, + unsigned explicit_alignment = 0); /** Constructor for sampler or image types */ glsl_type(GLenum gl_type, glsl_base_type base_type, @@ -1245,7 +1266,8 @@ private: /** Constructor for record types */ glsl_type(const glsl_struct_field *fields, unsigned num_fields, - const char *name, bool packed = false); + const char *name, bool packed = false, + unsigned explicit_alignment = 0); /** Constructor for interface types */ glsl_type(const glsl_struct_field *fields, unsigned num_fields, diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp index 9b4f9c5b0aa..1fff15c7cd5 100644 --- a/src/compiler/nir_types.cpp +++ b/src/compiler/nir_types.cpp @@ -860,6 +860,12 @@ glsl_get_explicit_size(const struct glsl_type *type, bool align_to_stride) return type->explicit_size(align_to_stride); } +unsigned +glsl_get_explicit_alignment(const struct glsl_type *type) +{ + return type->explicit_alignment; +} + bool glsl_type_is_packed(const struct glsl_type *type) { diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h index 2df1e2c8b9b..14fae6a5f58 100644 --- a/src/compiler/nir_types.h +++ b/src/compiler/nir_types.h @@ -122,6 +122,7 @@ void glsl_get_cl_type_size_align(const struct glsl_type *type, unsigned *size, unsigned *align); unsigned glsl_get_explicit_size(const struct glsl_type *type, bool align_to_stride); +unsigned glsl_get_explicit_alignment(const struct glsl_type *type); static inline unsigned glsl_get_bit_size(const struct glsl_type *type)