[Mesa-dev] [PATCH 3/5] glsl: Linker fills ir_variable::complete_location

Vincent Lejeune vljn at ovi.com
Tue Jan 24 13:05:12 PST 2012


This patch modify the assign_varying_locations function so that it
populates ir_variable::complete_location instead of
ir_variable::location. The final layout remains unchanged though.
Tfb_declaration is also updated to handles the use of the new
field.
---
 src/glsl/builtin_variables.cpp     |    2 +
 src/glsl/ir_set_program_inouts.cpp |   13 ++++-
 src/glsl/linker.cpp                |  115 +++++++++++++++++++++++++++++++-----
 3 files changed, 112 insertions(+), 18 deletions(-)

diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
index ed6b922..68aa81d 100644
--- a/src/glsl/builtin_variables.cpp
+++ b/src/glsl/builtin_variables.cpp
@@ -408,6 +408,8 @@ add_variable(exec_list *instructions, glsl_symbol_table *symtab,
 
    var->location = slot;
    var->explicit_location = (slot >= 0);
+   var->complete_location = location_tree_create(var, var->type);
+   set_vanilla_location_to_variable(var->complete_location, var->type, slot);
 
    /* Once the variable is created an initialized, add it to the symbol table
     * and add the declaration to the IR stream.
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
index 8c2bc30..e629705 100644
--- a/src/glsl/ir_set_program_inouts.cpp
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -81,12 +81,21 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
     */
 
    for (int i = 0; i < len; i++) {
-      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i);
+      unsigned location;
+      if (var->complete_location) {
+         unsigned size;
+         const struct register_info* tmp = get_register_info(var->complete_location,var->type,size);
+         location = tmp[0].index;
+         ralloc_free((void *)tmp);
+      } else {
+         location = var->location;
+      }
+      GLbitfield64 bitfield = BITFIELD64_BIT(location + offset + i);
       if (var->mode == ir_var_in) {
 	 prog->InputsRead |= bitfield;
          if (is_fragment_shader) {
             gl_fragment_program *fprog = (gl_fragment_program *) prog;
-            fprog->InterpQualifier[var->location + offset + i] =
+            fprog->InterpQualifier[location + offset + i] =
                (glsl_interp_qualifier) var->interpolation;
          }
       } else if (var->mode == ir_var_system_value) {
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 5095751..9c65f92 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1459,6 +1459,7 @@ private:
     */
    int location;
 
+   unsigned component_offset;
    /**
     * If location != -1, the number of vector elements in this variable, or 1
     * if this variable is a scalar.
@@ -1555,6 +1556,10 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
                                 struct gl_shader_program *prog,
                                 ir_variable *output_var)
 {
+   unsigned size;
+   const register_info *output_regs = get_register_info(output_var->complete_location, output_var->type, size);
+   unsigned output_var_location = output_regs[0].index;
+   this->component_offset = output_regs[0].writemask_offset;
    if (output_var->type->is_array()) {
       /* Array variable */
       const unsigned matrix_cols =
@@ -1573,14 +1578,14 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
          }
          if (this->is_clip_distance_mesa) {
             this->location =
-               output_var->location + this->array_subscript / 4;
+               output_var_location + this->array_subscript / 4;
          } else {
             this->location =
-               output_var->location + this->array_subscript * matrix_cols;
+               output_var_location + this->array_subscript * matrix_cols;
          }
          this->size = 1;
       } else {
-         this->location = output_var->location;
+         this->location = output_var_location;
          this->size = actual_array_size;
       }
       this->vector_elements = output_var->type->fields.array->vector_elements;
@@ -1597,7 +1602,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
                       this->orig_name, this->var_name);
          return false;
       }
-      this->location = output_var->location;
+      this->location = output_var_location;
       this->size = 1;
       this->vector_elements = output_var->type->vector_elements;
       this->matrix_columns = output_var->type->matrix_columns;
@@ -1687,7 +1692,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
       for (unsigned v = 0; v < this->matrix_columns; ++v) {
          unsigned num_components = this->vector_elements;
          assert(info->NumOutputs < max_outputs);
-         info->Outputs[info->NumOutputs].ComponentOffset = 0;
+         info->Outputs[info->NumOutputs].ComponentOffset = this->component_offset;
          if (this->is_clip_distance_mesa) {
             if (this->is_subscripted) {
                num_components = 1;
@@ -1811,6 +1816,29 @@ assign_varying_location(ir_variable *input_var, ir_variable *output_var,
 
 
 /**
+ * "Default" packing function, that in fact does pack any varyings.
+ * It affects location in order with a single field per reg.
+ */
+void
+default_packing_function(ir_variable **produced_var,
+                                         ir_variable **consumed_var,
+                                         unsigned size,
+                                         int *first_produced_index,
+                                         int *first_consumed_index)
+{
+   int p_index = *first_produced_index;
+   int c_index = *first_consumed_index;
+   for (unsigned i = 0; i < size; i++) {
+         set_vanilla_location_to_variable(produced_var[i]->complete_location, produced_var[i]->type, p_index);
+         if (consumed_var)
+            set_vanilla_location_to_variable(consumed_var[i]->complete_location, consumed_var[i]->type, c_index);
+   }
+   *first_produced_index = p_index;
+   *first_consumed_index = c_index;
+}
+
+
+/**
  * Assign locations for all variables that are produced in one pipeline stage
  * (the "producer") and consumed in the next stage (the "consumer").
  *
@@ -1838,9 +1866,22 @@ assign_varying_locations(struct gl_context *ctx,
                          tfeedback_decl *tfeedback_decls)
 {
    /* FINISHME: Set dynamically when geometry shader support is added. */
-   unsigned output_index = VERT_RESULT_VAR0;
-   unsigned input_index = FRAG_ATTRIB_VAR0;
-
+   int output_index = VERT_RESULT_VAR0;
+   int input_index = FRAG_ATTRIB_VAR0;
+   void *array_context = ralloc_context(NULL);
+   ir_variable **tfb_output_array = rzalloc_array(array_context, class ir_variable *, 1);
+   unsigned  tfb_output_array_shadow_size = 1;
+   unsigned *tfb_index = rzalloc_array(array_context, unsigned, 1);
+   unsigned tfb_index_shadow_size = 1;
+   unsigned tfb_size = 0;
+   ir_variable **output_array = rzalloc_array(array_context, class ir_variable *, 1);
+   unsigned output_array_shadow_size = 1;
+   ir_variable **input_array = rzalloc_array(array_context, class ir_variable *, 1);
+   unsigned input_array_shadow_size = 1;
+   unsigned varying_size = 0;
+   ir_variable **not_paired_output = rzalloc_array(array_context, class ir_variable *, 1);
+   unsigned not_paired_output_shadow_size = 1;
+   unsigned not_paired_output_size = 0;
    /* Operate in a total of three passes.
     *
     * 1. Assign locations for any matching inputs and outputs.
@@ -1869,23 +1910,65 @@ assign_varying_locations(struct gl_context *ctx,
          input_var = NULL;
 
       if (input_var) {
-         assign_varying_location(input_var, output_var, &input_index,
-                                 &output_index);
+	   varying_size ++;
+         DYNAMIC_RESIZE(array_context, output_array, class ir_variable *, varying_size, output_array_shadow_size);
+	   output_array[varying_size - 1] = output_var;
+         DYNAMIC_RESIZE(array_context, input_array, class ir_variable *, varying_size, input_array_shadow_size);
+	   input_array[varying_size - 1] = input_var;
+	   output_var->complete_location = location_tree_create(output_var, output_var->type);
+	   input_var->complete_location = location_tree_create(input_var, input_var->type);
+         continue;
       }
 
       for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
          if (!tfeedback_decls[i].is_assigned() &&
              tfeedback_decls[i].matches_var(output_var)) {
-            if (output_var->location == -1) {
-               assign_varying_location(input_var, output_var, &input_index,
-                                       &output_index);
-            }
-            if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
-               return false;
+		   tfb_size ++;
+               DYNAMIC_RESIZE(array_context, tfb_output_array, class ir_variable *, tfb_size, tfb_output_array_shadow_size);
+		   tfb_output_array[tfb_size - 1] = output_var;
+               DYNAMIC_RESIZE(array_context, tfb_index, unsigned, tfb_size, tfb_index_shadow_size);
+               tfb_index[tfb_size - 1] = i;
+               // If output has no associated input and is not a built-in varying, it needs to be affected a location, too.
+               if (!output_var->complete_location) {
+                  not_paired_output_size ++;
+                  DYNAMIC_RESIZE(array_context, not_paired_output, class ir_variable *, not_paired_output_size, not_paired_output_shadow_size);
+                  not_paired_output[not_paired_output_size - 1] = output_var;
+                  output_var->complete_location = location_tree_create(output_var, output_var->type);
+               }
          }
       }
    }
 
+   vec_packing_function(output_array, input_array, varying_size, &output_index, &input_index);
+
+   // Fills ir_variable::location to tells linker this var is used
+   for (unsigned i = 0; i < varying_size; i++) {
+      unsigned idx_in;
+      unsigned idx_out;
+      assign_varying_location(input_array[i], output_array[i], &idx_in,
+                              &idx_out);
+   }
+
+   vec_packing_function(not_paired_output, NULL, not_paired_output_size, &output_index, &input_index);
+
+   // Fills ir_variable::location to tells linker this var is used
+   for (unsigned i = 0; i < not_paired_output_size; i++) {
+      unsigned to_ditch;
+      assign_varying_location(NULL, not_paired_output[i], &to_ditch,
+                              &to_ditch);
+   }
+
+   // Propagate the changes to tfb
+   for (unsigned i = 0; i < tfb_size; i++) {
+      unsigned idx_ditch;
+      assign_varying_location(NULL, tfb_output_array[i], &idx_ditch,
+                              &idx_ditch);
+      if (!tfeedback_decls[tfb_index[i]].assign_location(ctx, prog, tfb_output_array[i]))
+	   return false;
+   }
+
+   ralloc_free(array_context);
+
    unsigned varying_vectors = 0;
 
    if (consumer) {
-- 
1.7.7



More information about the mesa-dev mailing list