[Mesa-dev] [PATCH 2/7] glsl: apply compile-time rules for the offset layout qualifier

Timothy Arceri timothy.arceri at collabora.com
Sun Jan 10 19:13:07 PST 2016


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



More information about the mesa-dev mailing list