On 17 January 2012 11:29, Christoph Bumiller <span dir="ltr"><<a href="mailto:e0425955@student.tuwien.ac.at">e0425955@student.tuwien.ac.at</a>></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 &x, const tfeedback_decl &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->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->size;<br>
+ if (this->is_clip_distance_mesa)<br>
+ translated_size = (translated_size + 3) / 4;<br>
+<br>
+ *count += translated_size * this->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->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->Outputs) >=<br>
- ctx->Const.MaxTransformFeedbackInterleavedComponents);<br>
- assert(Elements(info->Outputs) >=<br>
- ctx->Const.MaxTransformFeedbackSeparateComponents);<br>
-<br>
unsigned translated_size = this->size;<br>
if (this->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 < translated_size; ++index) {<br>
for (unsigned v = 0; v < this->matrix_columns; ++v) {<br>
unsigned num_components = this->vector_elements;<br>
+ assert(info->NumOutputs < max_outputs);<br>
info->Outputs[info->NumOutputs].ComponentOffset = 0;<br>
if (this->is_clip_distance_mesa) {<br>
if (this->is_subscripted) {<br>
@@ -1976,6 +1980,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,<br>
prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;<br>
<br>
ralloc_free(prog->LinkedTransformFeedback.Varyings);<br>
+ ralloc_free(prog->LinkedTransformFeedback.Outputs);<br>
<br>
memset(&prog->LinkedTransformFeedback, 0,<br>
sizeof(prog->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 < num_tfeedback_decls; ++i)<br>
+ if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs))<br>
+ return false;<br>
+<br>
+ prog->LinkedTransformFeedback.Outputs =<br>
+ rzalloc_array(prog->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->LinkedTransformFeedback.Outputs. See Mesa commit 5a0f395 ("glsl: Fix leak of LinkedTransformFeedback.Varyings.") from Eric Anholt for the parallel fix to prog->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 < num_tfeedback_decls; ++i) {<br>
unsigned buffer = separate_attribs_mode ? i : 0;<br>
if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,<br>
- buffer, i))<br>
+ buffer, i, num_outputs))<br>
return false;<br>
}<br>
+ assert(prog->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>