On 4 January 2012 11:38, Ian Romanick <span dir="ltr"><<a href="mailto:idr@freedesktop.org">idr@freedesktop.org</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">
<div class="im">On 01/03/2012 10:35 PM, Paul Berry wrote:<br>
</div><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It is not explicitly stated in the GL 3.0 spec that transform feedback<br>
can be performed on a whole varying array (without supplying a<br>
subscript). However, it seems clear from context that this was the<br>
intent. Section 2.15 (TransformFeedback) says this:<br>
<br>
When writing varying variables that are arrays, individual array<br>
elements are written in order.<br>
<br>
And section 2.20.3 (Shader Variables), says this, in the description<br>
of GetTransformFeedbackVarying:<br>
<br>
For the selected varying variable, its type is returned into<br>
type. The size of the varying is returned into size. The value in<br>
size is in units of the type returned in type.<br>
<br>
If it were not possible to perform transform feedback on an<br>
unsubscripted array, the returned size would always be 1.<br>
<br>
This patch fixes the linker so that transform feedback on an<br>
unsubscripted array is supported.<br>
<br>
Fixes piglit tests "EXT_transform_feedback/<u></u>builtin-varyings<br>
gl_ClipDistance[{4,8}]-no-<u></u>subscript" and<br>
"EXT_transform_feedback/<u></u>output_type *[2]-no-subscript".<br>
<br>
Note: on back-ends that set<br>
gl_shader_compiler_options::<u></u>LowerClipDistance (for example i965),<br>
tests "EXT_transform_feedback/<u></u>builtin-varyings<br>
gl_ClipDistance[{1,2,3,5,6,7}]<u></u>" still fail. I hope to address this in<br>
a later patch.<br>
</blockquote>
<br></div>
Other than the one comment below, which can be addressed later, this patch is<br>
<br>
Reviewed-by: Ian Romanick <<a href="mailto:ian.d.romanick@intel.com" target="_blank">ian.d.romanick@intel.com</a>><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
---<br>
src/glsl/linker.cpp | 99 ++++++++++++++++++++++++++++--<u></u>---------------------<br>
1 files changed, 54 insertions(+), 45 deletions(-)<br>
<br>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp<br>
index 45edafb..883a635 100644<br>
--- a/src/glsl/linker.cpp<br>
+++ b/src/glsl/linker.cpp<br>
@@ -1426,12 +1426,12 @@ private:<br>
/**<br>
* True if the declaration in orig_name represents an array.<br>
*/<br>
- bool is_array;<br>
+ bool is_subscripted;<br>
<br>
/**<br>
- * If is_array is true, the array index that was specified in orig_name.<br>
+ * If is_subscripted is true, the subscript that was specified in orig_name.<br>
*/<br>
- unsigned array_index;<br>
+ unsigned array_subscript;<br>
<br>
/**<br>
* Which component to extract from the vertex shader output location that<br>
@@ -1460,6 +1460,12 @@ private:<br>
<br>
/** Type of the varying returned by glGetTransformFeedbackVarying(<u></u>) */<br>
GLenum type;<br>
+<br>
+ /**<br>
+ * If location != -1, the size that should be returned by<br>
+ * glGetTransformFeedbackVarying(<u></u>).<br>
+ */<br>
+ unsigned size;<br>
};<br>
<br>
<br>
@@ -1484,14 +1490,14 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,<br>
<br>
if (bracket) {<br>
this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);<br></div></div>
- if (sscanf(bracket, "[%u]",&this->array_index) != 1) {<br>
+ if (sscanf(bracket, "[%u]",&this->array_subscript) != 1) {<div><div class="h5"><br>
linker_error(prog, "Cannot parse transform feedback varying %s", input);<br>
return false;<br>
}<br>
- this->is_array = true;<br>
+ this->is_subscripted = true;<br>
} else {<br>
this->var_name = ralloc_strdup(mem_ctx, input);<br>
- this->is_array = false;<br>
+ this->is_subscripted = false;<br>
}<br>
<br>
/* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, we need<br>
@@ -1501,8 +1507,10 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,<br>
if (ctx->ShaderCompilerOptions[<u></u>MESA_SHADER_VERTEX].<u></u>LowerClipDistance&&<br>
strcmp(this->var_name, "gl_ClipDistance") == 0) {<br>
this->var_name = "gl_ClipDistanceMESA";<br>
- this->single_component = this->array_index % 4;<br>
- this->array_index /= 4;<br>
+ if (this->is_subscripted) {<br>
+ this->single_component = this->array_subscript % 4;<br>
+ this->array_subscript /= 4;<br>
+ }<br>
}<br>
<br>
return true;<br>
@@ -1518,9 +1526,9 @@ tfeedback_decl::is_same(const tfeedback_decl&x, const tfeedback_decl&y)<br>
{<br>
if (strcmp(x.var_name, y.var_name) != 0)<br>
return false;<br>
- if (x.is_array != y.is_array)<br>
+ if (x.is_subscripted != y.is_subscripted)<br>
return false;<br></div></div>
- if (x.is_array&& x.array_index != y.array_index)<br>
+ if (x.is_subscripted&& x.array_subscript != y.array_subscript)<div><div class="h5"><br>
return false;<br>
if (x.single_component != y.single_component)<br>
return false;<br>
@@ -1542,37 +1550,39 @@ tfeedback_decl::assign_<u></u>location(struct gl_context *ctx,<br>
{<br>
if (output_var->type->is_array()) {<br>
/* Array variable */<br>
- if (!this->is_array) {<br>
- linker_error(prog, "Transform feedback varying %s found, "<br>
- "but array dereference required for varying %s[%d]).",<br>
- this->orig_name,<br>
- output_var->name, output_var->type->length);<br>
- return false;<br>
- }<br>
- /* Check array bounds. */<br>
- if (this->array_index>=<br>
- (unsigned) output_var->type->array_size()<u></u>) {<br>
- linker_error(prog, "Transform feedback varying %s has index "<br>
- "%i, but the array size is %i.",<br>
- this->orig_name, this->array_index,<br>
- output_var->type->array_size()<u></u>);<br>
- return false;<br>
- }<br>
const unsigned matrix_cols =<br>
output_var->type->fields.<u></u>array->matrix_columns;<br>
- this->location = output_var->location + this->array_index * matrix_cols;<br>
+<br>
+ if (this->is_subscripted) {<br>
+ /* Check array bounds. */<br>
+ if (this->array_subscript>=<br>
+ (unsigned) output_var->type->array_size()<u></u>) {<br>
+ linker_error(prog, "Transform feedback varying %s has index "<br>
+ "%i, but the array size is %i.",<br>
+ this->orig_name, this->array_subscript,<br>
+ output_var->type->array_size()<u></u>);<br>
+ return false;<br>
+ }<br>
+ this->location =<br>
+ output_var->location + this->array_subscript * matrix_cols;<br>
+ this->size = 1;<br>
+ } else {<br>
+ this->location = output_var->location;<br>
+ this->size = (unsigned) output_var->type->array_size()<u></u>;<br>
+ }<br>
this->vector_elements = output_var->type->fields.<u></u>array->vector_elements;<br>
this->matrix_columns = matrix_cols;<br>
- this->type = GL_NONE;<br>
+ this->type = output_var->type->fields.<u></u>array->gl_type;<br>
} else {<br>
/* Regular variable (scalar, vector, or matrix) */<br>
- if (this->is_array) {<br>
+ if (this->is_subscripted) {<br>
linker_error(prog, "Transform feedback varying %s found, "<br>
"but it's an array ([] expected).",<br>
this->orig_name);<br>
</div></div></blockquote>
<br>
I hadn't noticed this before, but this error message seems to not match the condition. The output variable (the varying) is not an array, but the transform feedback setting included an array subscript. Right?<div class="HOEnZb">
<div class="h5"><br></div></div></blockquote><div><br>You're right, that's a bogus error message. I'll submit a follow-up patch that fixes it.<br></div></div>