On 17 January 2012 11:29, Christoph Bumiller <span dir="ltr">&lt;<a href="mailto:e0425955@student.tuwien.ac.at">e0425955@student.tuwien.ac.at</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">
The nvc0 gallium driver is advertising 128 MAX_INTERLEAVED_COMPS<br>
which made it always assert in the linker when TFB was used since<br>
the Outputs array was smaller than that maximum.<br>
<br>
v2: added assertions<br>
<br>
NOTE: This is a candidate for the 8.0 branch.<br>
---<br>
 src/glsl/linker.cpp    |   64 ++++++++++++++++++++++++++++++------------------<br>
 src/mesa/main/mtypes.h |   32 ++++++++++++-----------<br>
 2 files changed, 57 insertions(+), 39 deletions(-)<br>
<br>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp<br>
index 0d85aee..b6c5754 100644<br>
--- a/src/glsl/linker.cpp<br>
+++ b/src/glsl/linker.cpp<br>
@@ -1388,9 +1388,10 @@ public:<br>
    static bool is_same(const tfeedback_decl &amp;x, const tfeedback_decl &amp;y);<br>
    bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,<br>
                         ir_variable *output_var);<br>
+   bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count);<br>
    bool store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
               struct gl_transform_feedback_info *info, unsigned buffer,<br>
-             unsigned varying) const;<br>
+              unsigned varying, const unsigned max_outputs) const;<br>
<br>
<br>
    /**<br>
@@ -1624,16 +1625,9 @@ tfeedback_decl::assign_location(struct gl_context *ctx,<br>
 }<br>
<br>
<br>
-/**<br>
- * Update gl_transform_feedback_info to reflect this tfeedback_decl.<br>
- *<br>
- * If an error occurs, the error is reported through linker_error() and false<br>
- * is returned.<br>
- */<br>
 bool<br>
-tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
-                      struct gl_transform_feedback_info *info,<br>
-                      unsigned buffer, unsigned varying) const<br>
+tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,<br>
+                                       unsigned *count)<br>
 {<br>
    if (!this-&gt;is_assigned()) {<br>
       /* From GL_EXT_transform_feedback:<br>
@@ -1648,6 +1642,28 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
       return false;<br>
    }<br>
<br>
+   unsigned translated_size = this-&gt;size;<br>
+   if (this-&gt;is_clip_distance_mesa)<br>
+      translated_size = (translated_size + 3) / 4;<br>
+<br>
+   *count += translated_size * this-&gt;matrix_columns;<br>
+<br>
+   return true;<br>
+}<br>
+<br>
+<br>
+/**<br>
+ * Update gl_transform_feedback_info to reflect this tfeedback_decl.<br>
+ *<br>
+ * If an error occurs, the error is reported through linker_error() and false<br>
+ * is returned.<br>
+ */<br>
+bool<br>
+tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
+                      struct gl_transform_feedback_info *info,<br>
+                      unsigned buffer,<br>
+                      unsigned varying, const unsigned max_outputs) const<br>
+{<br>
    /* From GL_EXT_transform_feedback:<br>
     *   A program will fail to link if:<br>
     *<br>
@@ -1663,19 +1679,6 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
       return false;<br>
    }<br>
<br>
-   /* Verify that the checks on MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS<br>
-    * and MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS are sufficient to prevent<br>
-    * overflow of info-&gt;Outputs[].  In worst case we generate one entry in<br>
-    * Outputs[] per component so a conservative check is to verify that the<br>
-    * size of the array is greater than or equal to both<br>
-    * MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS and<br>
-    * MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.<br>
-    */<br>
-   assert(Elements(info-&gt;Outputs) &gt;=<br>
-          ctx-&gt;Const.MaxTransformFeedbackInterleavedComponents);<br>
-   assert(Elements(info-&gt;Outputs) &gt;=<br>
-          ctx-&gt;Const.MaxTransformFeedbackSeparateComponents);<br>
-<br>
    unsigned translated_size = this-&gt;size;<br>
    if (this-&gt;is_clip_distance_mesa)<br>
       translated_size = (translated_size + 3) / 4;<br>
@@ -1683,6 +1686,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,<br>
    for (unsigned index = 0; index &lt; translated_size; ++index) {<br>
       for (unsigned v = 0; v &lt; this-&gt;matrix_columns; ++v) {<br>
          unsigned num_components = this-&gt;vector_elements;<br>
+         assert(info-&gt;NumOutputs &lt; max_outputs);<br>
          info-&gt;Outputs[info-&gt;NumOutputs].ComponentOffset = 0;<br>
          if (this-&gt;is_clip_distance_mesa) {<br>
             if (this-&gt;is_subscripted) {<br>
@@ -1976,6 +1980,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,<br>
       prog-&gt;TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;<br>
<br>
    ralloc_free(prog-&gt;LinkedTransformFeedback.Varyings);<br>
+   ralloc_free(prog-&gt;LinkedTransformFeedback.Outputs);<br>
<br>
    memset(&amp;prog-&gt;LinkedTransformFeedback, 0,<br>
           sizeof(prog-&gt;LinkedTransformFeedback));<br>
@@ -1988,12 +1993,23 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,<br>
                    struct gl_transform_feedback_varying_info,<br>
                    num_tfeedback_decls);<br>
<br>
+   unsigned num_outputs = 0;<br>
+   for (unsigned i = 0; i &lt; num_tfeedback_decls; ++i)<br>
+      if (!tfeedback_decls[i].accumulate_num_outputs(prog, &amp;num_outputs))<br>
+         return false;<br>
+<br>
+   prog-&gt;LinkedTransformFeedback.Outputs =<br>
+      rzalloc_array(prog-&gt;LinkedTransformFeedback.Outputs,<br>
+                    struct gl_transform_feedback_output,<br>
+                    num_outputs);<br></blockquote><div><br>I know I already gave you a review over IRC, but I just realized that this is a memory leak.  The first argument of rzalloc_array needs to be prog, not prog-&gt;LinkedTransformFeedback.Outputs.  See Mesa commit 5a0f395 (&quot;glsl: Fix leak of LinkedTransformFeedback.Varyings.&quot;) from Eric Anholt for the parallel fix to prog-&gt;LinkedTransformFeedback.Varyings.<br>
<br>Sorry for missing that on my earlier review.<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>
    for (unsigned i = 0; i &lt; num_tfeedback_decls; ++i) {<br>
       unsigned buffer = separate_attribs_mode ? i : 0;<br>
       if (!tfeedback_decls[i].store(ctx, prog, &amp;prog-&gt;LinkedTransformFeedback,<br>
-                                    buffer, i))<br>
+                                    buffer, i, num_outputs))<br>
          return false;<br>
    }<br>
+   assert(prog-&gt;LinkedTransformFeedback.NumOutputs == num_outputs);<br>
<br>
    return true;<br>
 }<br>
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h<br>
index 9fdabf9..95450f9 100644<br>
--- a/src/mesa/main/mtypes.h<br>
+++ b/src/mesa/main/mtypes.h<br>
@@ -1823,6 +1823,22 @@ struct gl_transform_feedback_varying_info {<br>
    GLint Size;<br>
 };<br>
<br>
+struct gl_transform_feedback_output {<br>
+   unsigned OutputRegister;<br>
+   unsigned OutputBuffer;<br>
+   unsigned NumComponents;<br>
+<br>
+   /** offset (in DWORDs) of this output within the interleaved structure */<br>
+   unsigned DstOffset;<br>
+<br>
+   /**<br>
+    * Offset into the output register of the data to output.  For example,<br>
+    * if NumComponents is 2 and ComponentOffset is 1, then the data to<br>
+    * offset is in the y and z components of the output register.<br>
+    */<br>
+   unsigned ComponentOffset;<br>
+};<br>
+<br>
 /** Post-link transform feedback info. */<br>
 struct gl_transform_feedback_info {<br>
    unsigned NumOutputs;<br>
@@ -1832,21 +1848,7 @@ struct gl_transform_feedback_info {<br>
     */<br>
    unsigned NumBuffers;<br>
<br>
-   struct {<br>
-      unsigned OutputRegister;<br>
-      unsigned OutputBuffer;<br>
-      unsigned NumComponents;<br>
-<br>
-      /** offset (in DWORDs) of this output within the interleaved structure */<br>
-      unsigned DstOffset;<br>
-<br>
-      /**<br>
-       * Offset into the output register of the data to output.  For example,<br>
-       * if NumComponents is 2 and ComponentOffset is 1, then the data to<br>
-       * offset is in the y and z components of the output register.<br>
-       */<br>
-      unsigned ComponentOffset;<br>
-   } Outputs[MAX_PROGRAM_OUTPUTS];<br>
+   struct gl_transform_feedback_output *Outputs;<br>
<br>
    /** Transform feedback varyings used for the linking of this shader program.<br>
     *<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.3.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">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>