Mesa (master): linker: Add padding after the last field of a structure

Ian Romanick idr at kemper.freedesktop.org
Mon Aug 4 21:40:44 UTC 2014


Module: Mesa
Branch: master
Commit: 7f731340d25b0c4a86ec3cc7b9a33f66c4818c2b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7f731340d25b0c4a86ec3cc7b9a33f66c4818c2b

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Wed Jul 16 15:40:32 2014 -0700

linker: Add padding after the last field of a structure

This causes the thing following the structure to be vec4-aligned.

Fixes gles3conform failures in:

ES3-CTS.shaders.uniform_block.random.nested_structs.2
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.5

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
Reviewed-by: Matt Turner <mattst88 at gmail.com>

---

 src/glsl/glsl_types.cpp          |   10 ++++++++--
 src/glsl/link_uniform_blocks.cpp |   13 +++++++++++++
 src/glsl/link_uniforms.cpp       |    5 ++++-
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 737e6dd..50e4fe5 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -934,14 +934,20 @@ glsl_type::std140_size(bool row_major) const
     */
    if (this->is_record()) {
       unsigned size = 0;
+      unsigned max_align = 0;
+
       for (unsigned i = 0; i < this->length; i++) {
 	 const struct glsl_type *field_type = this->fields.structure[i].type;
 	 unsigned align = field_type->std140_base_alignment(row_major);
 	 size = glsl_align(size, align);
 	 size += field_type->std140_size(row_major);
+
+         max_align = MAX2(align, max_align);
+
+         if (field_type->is_record() && (i + 1 < this->length))
+            size = glsl_align(size, 16);
       }
-      size = glsl_align(size,
-			this->fields.structure[0].type->std140_base_alignment(row_major));
+      size = glsl_align(size, max_align);
       return size;
    }
 
diff --git a/src/glsl/link_uniform_blocks.cpp b/src/glsl/link_uniform_blocks.cpp
index ddd134a..3768205 100644
--- a/src/glsl/link_uniform_blocks.cpp
+++ b/src/glsl/link_uniform_blocks.cpp
@@ -104,7 +104,20 @@ private:
 
       this->offset = glsl_align(this->offset, alignment);
       v->Offset = this->offset;
+
+      /* If this is the last field of a structure, apply rule #9.  The
+       * GL_ARB_uniform_buffer_object spec says:
+       *
+       *     "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."
+       *
+       * last_field won't be set if this is the last field of a UBO that is
+       * not a named instance.
+       */
       this->offset += size;
+      if (last_field)
+         this->offset = glsl_align(this->offset, 16);
 
       /* From the GL_ARB_uniform_buffer_object spec:
        *
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
index 8014a3d..cfb23ef 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -513,7 +513,7 @@ private:
 
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major, const glsl_type *record_type,
-                            bool /* last_field */)
+                            bool last_field)
    {
       assert(!type->without_array()->is_record());
       assert(!type->without_array()->is_interface());
@@ -582,6 +582,9 @@ private:
 	 this->uniforms[id].offset = this->ubo_byte_offset;
 	 this->ubo_byte_offset += type->std140_size(ubo_row_major);
 
+         if (last_field)
+            this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16);
+
 	 if (type->is_array()) {
 	    this->uniforms[id].array_stride =
 	       glsl_align(type->fields.array->std140_size(ubo_row_major), 16);




More information about the mesa-commit mailing list