[Mesa-dev] [PATCH 5/7] glsl: rework the way varying location are assigned to prepare varying packing

Vincent Lejeune vljn at ovi.com
Thu Feb 16 13:03:11 PST 2012


---
 src/glsl/linker.cpp |  125 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 74 insertions(+), 51 deletions(-)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 8e690ac..4a5e3bb 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1813,6 +1813,36 @@ assign_varying_location(ir_variable *input_var, ir_variable *output_var,
    }
 }
 
+namespace pack {
+
+class varying_info : public exec_node
+{
+public:
+   ir_variable *produced;
+   ir_variable *consumed;
+   varying_info( ir_variable *p, ir_variable *c)
+      : produced(p), consumed(c)
+   {
+
+   }
+};
+
+bool
+varying_pack_avoid(exec_list *lst, gl_shader_program *prog, unsigned max_varyings)
+{
+   unsigned input_index = FRAG_ATTRIB_VAR0, output_index = VERT_RESULT_VAR0;
+   foreach_list_const(node, lst) {
+	const varying_info *vi = (class varying_info *) node;
+	assign_varying_location(vi->consumed, vi->produced, &input_index, &output_index);
+   }
+
+   unsigned varyings_count = MAX2(input_index - FRAG_ATTRIB_VAR0, output_index - VERT_RESULT_VAR0);
+   if (varyings_count > max_varyings) {
+	linker_error(prog, "This driver does not support packing, too much varyings.");
+	return false;
+   }
+   return true;
+}
 
 /**
  * Assign locations for all variables that are produced in one pipeline stage
@@ -1841,10 +1871,9 @@ assign_varying_locations(struct gl_context *ctx,
                          unsigned num_tfeedback_decls,
                          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;
-
+   void *rctx = ralloc_context(NULL);
+   exec_list *delayed_assignment = new (rctx) exec_list();
+   
    /* Operate in a total of three passes.
     *
     * 1. Assign locations for any matching inputs and outputs.
@@ -1872,26 +1901,58 @@ assign_varying_locations(struct gl_context *ctx,
       if (input_var && input_var->mode != ir_var_in)
          input_var = NULL;
 
+      varying_info *vi = NULL;
+
       if (input_var) {
-         assign_varying_location(input_var, output_var, &input_index,
-                                 &output_index);
+         vi = new (rctx) varying_info (output_var, input_var);
+         delayed_assignment->push_tail(vi);
       }
 
       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 (output_var->location != -1) {
+               if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) {
+                  ralloc_free(rctx);
+                  return false;
+               }
+            } else if (!vi) {
+               vi = new (rctx) varying_info (output_var, NULL);
+               delayed_assignment->push_tail(vi);
             }
-            if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
-               return false;
          }
       }
    }
 
-   unsigned varying_vectors = 0;
+   bool (* varying_pack)(exec_list *, gl_shader_program *, unsigned);
+
+   switch (ctx->ShaderCompilerOptions[0].VaryingsPackingConstraint) {
+   default:
+      varying_pack = varying_pack_avoid;
+      break;
+   }
 
+   if (!varying_pack(delayed_assignment, prog, ctx->Const.MaxVarying)) {
+      ralloc_free(rctx);
+      return false;
+   }
+   
+   // Do TFB assignments
+   foreach_list(node, delayed_assignment) {
+      varying_info *vi = (varying_info *) node;
+      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+         printf("name is %s, at %d,%d\n", vi->produced->name, vi->produced->location, vi->produced->horizontal_location);
+         printf("assigned is %d\n",tfeedback_decls[i].matches_var(vi->produced));
+         if (!tfeedback_decls[i].is_assigned() &&
+             tfeedback_decls[i].matches_var(vi->produced)) {
+            if (!tfeedback_decls[i].assign_location(ctx, prog, vi->produced)) {
+               ralloc_free(rctx);
+               return false;
+            }
+         }
+      }
+   }
+   
    if (consumer) {
       foreach_list(node, consumer->ir) {
          ir_variable *const var = ((ir_instruction *) node)->as_variable();
@@ -1922,48 +1983,10 @@ assign_varying_locations(struct gl_context *ctx,
              * value is written by the previous stage.
              */
             var->mode = ir_var_auto;
-         } else {
-            /* The packing rules are used for vertex shader inputs are also
-             * used for fragment shader inputs.
-             */
-            varying_vectors += count_attribute_slots(var->type);
          }
       }
    }
-
-   if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
-      if (varying_vectors > ctx->Const.MaxVarying) {
-         if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
-            linker_warning(prog, "shader uses too many varying vectors "
-                           "(%u > %u), but the driver will try to optimize "
-                           "them out; this is non-portable out-of-spec "
-                           "behavior\n",
-                           varying_vectors, ctx->Const.MaxVarying);
-         } else {
-            linker_error(prog, "shader uses too many varying vectors "
-                         "(%u > %u)\n",
-                         varying_vectors, ctx->Const.MaxVarying);
-            return false;
-         }
-      }
-   } else {
-      const unsigned float_components = varying_vectors * 4;
-      if (float_components > ctx->Const.MaxVarying * 4) {
-         if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
-            linker_warning(prog, "shader uses too many varying components "
-                           "(%u > %u), but the driver will try to optimize "
-                           "them out; this is non-portable out-of-spec "
-                           "behavior\n",
-                           float_components, ctx->Const.MaxVarying * 4);
-         } else {
-            linker_error(prog, "shader uses too many varying components "
-                         "(%u > %u)\n",
-                         float_components, ctx->Const.MaxVarying * 4);
-            return false;
-         }
-      }
-   }
-
+   ralloc_free(rctx);
    return true;
 }
 
-- 
1.7.7



More information about the mesa-dev mailing list