This implements the rules for the offset qualifier on block members. From Section 4.4.5 (Uniform and Shader Storage Block Layout Qualifiers) of the GLSL 4.50 spec:
"The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." ... "It is a compile-time error to specify an offset that is smaller than the offset of the previous member in the block or that lies within the previous member of the block." ... "The specified offset must be a multiple of the base alignment of the type of the block member it qualifies, or a compile-time error results." --- src/glsl/ast_to_hir.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 480af37..ee21738 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -6215,6 +6215,7 @@ ast_process_struct_or_iface_block_members(exec_list *instructions, unsigned expl_location) { unsigned decl_count = 0; + unsigned next_offset = 0; /* Make an initial pass over the list of fields to determine how * many there are. Each element in this list is an ast_declarator_list. @@ -6419,6 +6420,54 @@ ast_process_struct_or_iface_block_members(exec_list *instructions, } } + /* Offset can only be used with std430 and std140 layouts an initial + * value of 0 is used for error detection. + */ + unsigned align = 0; + unsigned size = 0; + if (layout) { + bool row_major; + if (qual->flags.q.row_major || + matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + row_major = true; + } else { + row_major = false; + } + + if(layout->flags.q.std140) { + align = field_type->std140_base_alignment(row_major); + size = field_type->std140_size(row_major); + } else if (layout->flags.q.std430) { + align = field_type->std430_base_alignment(row_major); + size = field_type->std430_size(row_major); + } + } + + if (qual->flags.q.explicit_offset) { + unsigned qual_offset; + if (process_qualifier_constant(state, &loc, "offset", + qual->offset, &qual_offset)) { + if (align != 0 && size != 0) { + if (next_offset > qual_offset) + _mesa_glsl_error(&loc, state, "layout qualifier " + "offset overlaps previous member"); + + if (qual_offset % align) { + _mesa_glsl_error(&loc, state, "layout qualifier offset " + "must be a multiple of the base " + "alignment of %s", field_type->name); + } + next_offset = glsl_align(qual_offset + size, align); + } else { + _mesa_glsl_error(&loc, state, "offset can only be used " + "with std430 and std140 layouts"); + } + } + } else { + if (align != 0 && size != 0) + next_offset = glsl_align(next_offset + size, align); + } + /* Propogate row- / column-major information down the fields of the * structure or interface block. Structures need this data because * the structure may contain a structure that contains ... a matrix -- 2.4.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev