summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorTimothy Arceri <[email protected]>2015-12-30 11:09:22 +1100
committerTimothy Arceri <[email protected]>2016-03-05 19:38:30 +1100
commit8abed7f185329250adf9f8c90a131797feda83b6 (patch)
tree383f70f4bd85ac09a5c65abef4d9fa632ed282a6 /src/compiler
parent6f45484ac7142d9ccda6ee009a0902147f62c75b (diff)
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 <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp49
1 files changed, 49 insertions, 0 deletions
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