[Mesa-dev] [PATCH 10/10] glsl/linker: Pack between varyings.

Paul Berry stereotype441 at gmail.com
Tue Dec 11 15:09:16 PST 2012


This patch implements varying packing between varyings.

Previously, each varying occupied components 0 through N-1 of its
assigned varying slot, so there was no way to pack two varyings into
the same slot.  For example, if the varyings were a float, a vec2, a
vec3, and another vec2, they would be stored as follows:

 <----slot1----> <----slot2----> <----slot3----> <----slot4---->  slots
  *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
 flt  x   x   x  <vec2->  x   x  <--vec3--->  x  <vec3->  x   x   varyings

(Each * represents a varying component, and the "x"s represent wasted
space).

This change packs the varyings together to eliminate wasted space
between varyings, like so:

 <----slot1----> <----slot2----> <----slot3----> <----slot4---->  slots
  *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
 <vec2-> <vec2-> flt <--vec3--->  x   x   x   x   x   x   x   x   varyings

Note that we take advantage of the sort order introduced in previous
patches (vec4's first, then vec2's, then scalars, then vec3's) to
minimize how often a varying is "double parked" (split across varying
slots).
---
 src/glsl/linker.cpp | 49 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 12 deletions(-)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index d6f11a5..80aa260 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1996,6 +1996,7 @@ private:
 
    static unsigned compute_packing_class(ir_variable *var);
    static packing_order_enum compute_packing_order(ir_variable *var);
+   static unsigned compute_num_components(ir_variable *var);
    static int match_comparator(const void *x_generic, const void *y_generic);
 
    /**
@@ -2012,6 +2013,7 @@ private:
        * Packing order for this varying, computed by compute_packing_order().
        */
       packing_order_enum packing_order;
+      unsigned num_components;
 
       /**
        * The output variable in the producer stage.
@@ -2099,6 +2101,8 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
       = this->compute_packing_class(producer_var);
    this->matches[this->num_matches].packing_order
       = this->compute_packing_order(producer_var);
+   this->matches[this->num_matches].num_components
+      = this->compute_num_components(producer_var);
    this->matches[this->num_matches].producer_var = producer_var;
    this->matches[this->num_matches].consumer_var = consumer_var;
    this->num_matches++;
@@ -2122,20 +2126,19 @@ varying_matches::assign_locations()
    unsigned generic_location = 0;
 
    for (unsigned i = 0; i < this->num_matches; i++) {
-      this->matches[i].generic_location = generic_location;
-
-      ir_variable *producer_var = this->matches[i].producer_var;
-
-      if (producer_var->type->is_array()) {
-         const unsigned slots = producer_var->type->length
-            * producer_var->type->fields.array->matrix_columns;
+      /* Advance to the next slot if this varying has a different packing
+       * class than the previous one, and we're not already on a slot
+       * boundary.
+       */
+      if (i > 0 && generic_location % 4 != 0 &&
+          this->matches[i - 1].packing_class
+          != this->matches[i].packing_class) {
+         generic_location += 4 - generic_location % 4;
+      }
 
-         generic_location += 4 * slots;
-      } else {
-         const unsigned slots = producer_var->type->matrix_columns;
+      this->matches[i].generic_location = generic_location;
 
-         generic_location += 4 * slots;
-      }
+      generic_location += this->matches[i].num_components;
    }
 
    return (generic_location + 3) / 4;
@@ -2219,6 +2222,28 @@ varying_matches::compute_packing_order(ir_variable *var)
 
 
 /**
+ * Compute the number of components that this variable will occupy when
+ * properly packed.
+ */
+unsigned
+varying_matches::compute_num_components(ir_variable *var)
+{
+   const glsl_type *type = var->type;
+   unsigned multipiler = 1;
+
+   if (type->is_array()) {
+      multipiler *= type->length;
+      type = type->fields.array;
+   }
+
+   /* FINISHME: Support for "varying" records in GLSL 1.50. */
+   assert(!type->is_record());
+
+   return multipiler * type->components();
+}
+
+
+/**
  * Comparison function passed to qsort() to sort varyings by packing_class and
  * then by packing_order.
  */
-- 
1.8.0.1



More information about the mesa-dev mailing list