[Mesa-dev] [PATCH 4/6] glsl: Update lower_packed_varyings to handle varying structs.

Paul Berry stereotype441 at gmail.com
Mon Jan 21 14:16:24 PST 2013


This patch adds code to lower_packed_varyings to handle varyings of
type struct.  Varying structs are currently packed in the most naive
possible way (in declaration order, with no gaps), so there is a
potential loss of runtime efficiency.  In a later patch it would be
nice to replace this with a "flattening" approach (wherein a varying
struct is flattened to individual varyings corresponding to each of
its structure elements), so that the linker can align each structure
element independently.  However, that would require a significantly
more complex implementation.
---
 src/glsl/lower_packed_varyings.cpp | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/src/glsl/lower_packed_varyings.cpp b/src/glsl/lower_packed_varyings.cpp
index 8f05752..8a40f5e 100644
--- a/src/glsl/lower_packed_varyings.cpp
+++ b/src/glsl/lower_packed_varyings.cpp
@@ -70,6 +70,10 @@
  * This lowering pass also packs flat floats, ints, and uints together, by
  * using ivec4 as the base type of flat "varyings", and using appropriate
  * casts to convert floats and uints into ints.
+ *
+ * This lowering pass also handles varyings whose type is a struct or an array
+ * of struct.  Structs are packed in order and with no gaps, so there may be a
+ * performance penalty due to structure elements being double-parked.
  */
 
 #include "glsl_symbol_table.h"
@@ -274,10 +278,20 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
                                             ir_variable *unpacked_var,
                                             const char *name)
 {
-   /* FINISHME: Support for "varying" records in GLSL 1.50. */
-   assert(!rvalue->type->is_record());
-
-   if (rvalue->type->is_array()) {
+   if (rvalue->type->is_record()) {
+      for (unsigned i = 0; i < rvalue->type->length; i++) {
+         if (i != 0)
+            rvalue = rvalue->clone(this->mem_ctx, NULL);
+         const char *field_name = rvalue->type->fields.structure[i].name;
+         ir_dereference_record *dereference_record = new(this->mem_ctx)
+            ir_dereference_record(rvalue, field_name);
+         char *deref_name
+            = ralloc_asprintf(this->mem_ctx, "%s.%s", name, field_name);
+         fine_location = this->lower_rvalue(dereference_record, fine_location,
+                                            unpacked_var, deref_name);
+      }
+      return fine_location;
+   } else if (rvalue->type->is_array()) {
       /* Arrays are packed/unpacked by considering each array element in
        * sequence.
        */
-- 
1.8.1.1



More information about the mesa-dev mailing list