diff options
Diffstat (limited to 'mesalib/src/glsl/lower_ubo_reference.cpp')
-rw-r--r-- | mesalib/src/glsl/lower_ubo_reference.cpp | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 3cdfc04ac..43dd067fa 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -111,7 +111,7 @@ is_dereferenced_thing_row_major(const ir_dereference *deref) case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR: return false; case GLSL_MATRIX_LAYOUT_ROW_MAJOR: - return matrix || deref->type->is_record(); + return matrix || deref->type->without_array()->is_record(); } unreachable("invalid matrix layout"); @@ -301,7 +301,14 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) deref = deref_array->array->as_dereference(); break; } else { - array_stride = deref_array->type->std140_size(row_major); + /* Whether or not the field is row-major (because it might be a + * bvec2 or something) does not affect the array itself. We need + * to know whether an array element in its entirety is row-major. + */ + const bool array_row_major = + is_dereferenced_thing_row_major(deref_array); + + array_stride = deref_array->type->std140_size(array_row_major); array_stride = glsl_align(array_stride, 16); } @@ -327,6 +334,15 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) const glsl_type *struct_type = deref_record->record->type; unsigned intra_struct_offset = 0; + /* glsl_type::std140_base_alignment doesn't grok interfaces. Use + * 16-bytes for the alignment because that is the general minimum of + * std140. + */ + const unsigned struct_alignment = struct_type->is_interface() + ? 16 + : struct_type->std140_base_alignment(row_major); + + for (unsigned int i = 0; i < struct_type->length; i++) { const glsl_type *type = struct_type->fields.structure[i].type; @@ -346,6 +362,19 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) deref_record->field) == 0) break; intra_struct_offset += type->std140_size(field_row_major); + + /* If the field just examined was itself a structure, apply rule + * #9: + * + * "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 (type->without_array()->is_record()) { + intra_struct_offset = glsl_align(intra_struct_offset, + struct_alignment); + + } } const_offset += intra_struct_offset; |