glsl: Use alignment of container record for its first field
authorIan Romanick <ian.d.romanick@intel.com>
Sat, 17 Aug 2013 07:27:43 +0000 (00:27 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 19 Aug 2013 23:39:04 +0000 (16:39 -0700)
The first field of a record in a UBO has the aligment of the record
itself.

Fixes piglit vs-struct-pad, fs-struct-pad, and (with the patch posted to
the piglit list that extends the test) layout-std140.

NOTE: The bit of strangeness with the version of visit_field without the
record_type poitner is because that method is pure virtual in the base
class.  The original implementation of the class did this to ensure
derived classes remembered to implement that flavor.  Now they can
implement either flavor but not both.  I don't know a C++ way to enforce
that.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68195
Cc: "9.2 9.1" mesa-stable@lists.freedesktop.org
src/glsl/link_uniform_blocks.cpp
src/glsl/link_uniforms.cpp

index 1083653c7d6db27a1fab50104c2af3d78f938a48..d9607584970f31c6643f175ca2ea1f62f36430cb 100644 (file)
@@ -58,6 +58,15 @@ public:
 private:
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major)
+   {
+      (void) type;
+      (void) name;
+      (void) row_major;
+      assert(!"Should not get here.");
+   }
+
+   virtual void visit_field(const glsl_type *type, const char *name,
+                            bool row_major, const glsl_type *record_type)
    {
       assert(this->index < this->num_variables);
 
@@ -85,7 +94,9 @@ private:
          v->IndexName = v->Name;
       }
 
-      unsigned alignment = type->std140_base_alignment(v->RowMajor);
+      const unsigned alignment = record_type
+        ? record_type->std140_base_alignment(v->RowMajor)
+        : type->std140_base_alignment(v->RowMajor);
       unsigned size = type->std140_size(v->RowMajor);
 
       this->offset = glsl_align(this->offset, alignment);
@@ -107,6 +118,10 @@ private:
 
    virtual void visit_field(const glsl_struct_field *field)
    {
+      /* FINISHME: When support for doubles (dvec4, etc.) is added to the
+       * FINISHME: compiler, this may be incorrect for a structure in a UBO
+       * FINISHME: like struct s { struct { float f } s1; dvec4 v; };.
+       */
       this->offset = glsl_align(this->offset,
                                 field->type->std140_base_alignment(false));
    }
index 095895bf27e122564f1361b8599f43b7650900ef..fa77157f78dde4092d0c254a8bd7413e291c4ea4 100644 (file)
@@ -401,6 +401,15 @@ private:
 
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major)
+   {
+      (void) type;
+      (void) name;
+      (void) row_major;
+      assert(!"Should not get here.");
+   }
+
+   virtual void visit_field(const glsl_type *type, const char *name,
+                            bool row_major, const glsl_type *record_type)
    {
       assert(!type->is_record());
       assert(!(type->is_array() && type->fields.array->is_record()));
@@ -446,7 +455,9 @@ private:
       if (this->ubo_block_index != -1) {
         this->uniforms[id].block_index = this->ubo_block_index;
 
-        unsigned alignment = type->std140_base_alignment(ubo_row_major);
+        const unsigned alignment = record_type
+           ? record_type->std140_base_alignment(ubo_row_major)
+           : type->std140_base_alignment(ubo_row_major);
         this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment);
         this->uniforms[id].offset = this->ubo_byte_offset;
         this->ubo_byte_offset += type->std140_size(ubo_row_major);