Sorry I missed the first round of feedback on these patches.  I hope my comments aren&#39;t coming too late.<br><br>On 1 November 2011 12:48, Marek Olšák <span dir="ltr">&lt;<a href="mailto:maraeo@gmail.com" target="_blank">maraeo@gmail.com</a>&gt;</span> wrote:<br>
<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


From: Dan McCabe &lt;<a href="mailto:zen3d.linux@gmail.com" target="_blank">zen3d.linux@gmail.com</a>&gt;<br>
<br>
Modify the linker to assign additional slots for varying<br>
variables used by transform feedback. This is done after other<br>
varyings are already assigned slots.<br>
<br>
Since this is done after previous varying slot assignments,<br>
the code needs to know how many varyings are already assigned<br>
slots. A new function &quot;max_varying()&quot; is introduced to examine a<br>
previously processed shader to find the largest varying already<br>
assigned a slot. All new varyings will be assigned slots after<br>
this one. If varyings are found, -1 is returned.<br>
<br>
[ Marek Olšák: fix segfault in accessing names ]<br>
---<br>
 src/glsl/linker.cpp |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 1 files changed, 84 insertions(+), 0 deletions(-)<br>
<br>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp<br>
index beadec6..e6012bf 100644<br>
--- a/src/glsl/linker.cpp<br>
+++ b/src/glsl/linker.cpp<br>
@@ -207,6 +207,25 @@ invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,<br>
    }<br>
 }<br>
<br>
+<br>
+int<br>
+max_varying(gl_shader *sh, enum ir_variable_mode mode)<br>
+{<br>
+   int max_varying = -1;<br>
+<br>
+   foreach_list(node, sh-&gt;ir) {<br>
+      ir_variable *const var = ((ir_instruction *) node)-&gt;as_variable();<br>
+<br>
+      if ((var == NULL) || (var-&gt;mode != (unsigned) mode))<br>
+        continue;<br>
+<br>
+      if (var-&gt;location &gt; max_varying)<br>
+        max_varying = var-&gt;location;<br>
+   }<br>
+<br>
+   return max_varying;<br>
+}<br></blockquote><div><br>A few comments on this function:<br><br>1. It should be declared static, since it&#39;s only used in this file.<br><br>2. Since it&#39;s only called with mode == ir_var_out, it might make more sense to drop that argument and call the function max_out_location().<br>



<br>3. Judging by how the return value of this function is used (it has 1 added to it and then the value is adjusted to be at least VERT_RESULT_VAR0), it seems like the real purpose of this function is to figure out the first slot into which varyings can be safely assigned.  Consider renaming this function to something like &quot;find_free_varying_slots&quot; and having it return the first slot into which varyings can be safely assigned.<br>


<br>4. This function might be unnecessary--see my comment below.<br>


 </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">
+<br>
<br>
 /**<br>
  * Determine the number of attribute slots required for a particular type<br>
@@ -1597,6 +1616,69 @@ assign_varying_locations(struct gl_context *ctx,<br>
<br>
<br>
 void<br>
+assign_transform_feedback_varying_locations(struct gl_context *ctx,<br>
+                                           struct gl_shader_program *prog) <br></blockquote><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">

+{<br>
+   struct gl_shader *vs = prog-&gt;_LinkedShaders[MESA_SHADER_VERTEX];<br>
+<br>
+   if (vs == NULL)<br>
+      return;<br>
+<br>
+   char **names = prog-&gt;TransformFeedback.VaryingNames;<br>
+   int num_names = prog-&gt;TransformFeedback.NumVarying;<br>
+<br>
+   if (num_names &lt;= 0)<br>
+      return;<br>
+<br>
+   int num_varying = max_varying(vs, ir_var_out) + 1;<br>
+   unsigned output_index =<br>
+     (num_varying &gt; VERT_RESULT_VAR0)<br>
+        ? num_varying<br>
+        : VERT_RESULT_VAR0;<br></blockquote><div><br>The effect of this code is to just recompute the value that output_index had when assign_varying_locations() finished.  Wouldn&#39;t it be better to just have assign_varying_locations() just store the value of output_index somewhere so we can retrieve it here?<br>
<br>Or, perhaps it would be better to merge all of this code into assign_varying_locations().  Really, both of these functions are doing the same task, they are just using different criteria (assign_varying_locations assigns locations to vertex shader outputs if they are used by the fragment shader, this function assigns locations to vertex shader outputs if they are used by transform feedback).<br>
 </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
+<br>
+   foreach_list(node, vs-&gt;ir) {<br>
+      ir_variable *const output_var = ((ir_instruction *) node)-&gt;as_variable();<br>
+<br>
+      if (output_var == NULL<br>
+      ||  output_var-&gt;mode != ir_var_out<br>
+      ||  output_var-&gt;location != -1)<br>
+        continue;<br>
+<br>
+      /* Find a transform feedback varying variable that has<br>
+       * the same name as the shader variable.<br>
+       */<br>
+      int varying_index = -1;<br>
+      for (int num_name = 0; num_name &lt; num_names; num_name++) {<br>
+         char *name = names[num_name];<br>
+         if (strcmp(output_var-&gt;name, name) == 0) {<br>
+            varying_index = num_name;<br>
+            break;<br>
+         }<br>
+      }<br>
+<br>
+      if (varying_index == -1)<br>
+        continue;<br>
+<br>
+      output_var-&gt;location = output_index;<br>
+<br>
+      /* FINISHME: Support for &quot;varying&quot; records in GLSL 1.50. */<br>
+      assert(!output_var-&gt;type-&gt;is_record());<br>
+<br>
+      if (output_var-&gt;type-&gt;is_array()) {<br>
+        const unsigned slots = output_var-&gt;type-&gt;length<br>
+           * output_var-&gt;type-&gt;fields.array-&gt;matrix_columns;<br>
+<br>
+        output_index += slots;<br>
+      } else {<br>
+        const unsigned slots = output_var-&gt;type-&gt;matrix_columns;<br>
+<br>
+        output_index += slots;<br>
+      }<br></blockquote><div><br>Aside: I have just realized that the technique we used to implement the gl_ClipDistance[] array (to lower it from an array of 8 floats to an array of 2 vec4s) is going to throw a monkeywrench into transform feedback of gl_ClipDistance.  I&#39;ll make sure to add that to the transform feedback tests I&#39;m writing.<br>


 </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">
+   }<br>
+}<br></blockquote><div><br>I don&#39;t see any error checking to make sure that we don&#39;t exceed the value of ctx-&gt;Const.MaxVarying.  (According to the EXT_transform_feedback spec, &quot;Varying variables specified by TransformFeedbackVaryingsEXT are always considered active and count against the total limit on the number of active varying components, regardless of the needs of the fragment shader.&quot;).  Normally this check would be done in assign_varying_locations(), but that function finishes before this one is called.  This is another argument, IMHO, for merging the two functions together.<br>
 </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">


+<br>
+<br>
+void<br>
 link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)<br>
 {<br>
    void *mem_ctx = ralloc_context(NULL); // temporary linker context<br>
@@ -1778,6 +1860,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)<br>
       prev = i;<br>
    }<br>
<br>
+   assign_transform_feedback_varying_locations(ctx, prog);<br>
+<br>
    if (prog-&gt;_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {<br>
       demote_shader_inputs_and_outputs(prog-&gt;_LinkedShaders[MESA_SHADER_VERTEX],<br>
                                       ir_var_out);<br>
<span><font color="#888888">--<br>
1.7.4.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br>