From 8abed7f185329250adf9f8c90a131797feda83b6 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 30 Dec 2015 11:09:22 +1100 Subject: [PATCH] glsl: apply compile-time rules for the offset layout qualifier 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." Reviewed-by: Edward O'Callaghan --- src/compiler/glsl/ast_to_hir.cpp | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 7e928c48e0e..cd94fa05845 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -6247,6 +6247,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. @@ -6460,6 +6461,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.30.2