On 19 January 2012 18:28, Paul Berry <span dir="ltr"><<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</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">
i965 processes assignments of whole structures using<br>
vec4_visitor::emit_block_move, a recursive function which visits each<br>
element of a structure or array (to arbitrary nesting depth) and<br>
copies it from the source to the destination. Then it increments the<br>
source and destination register numbers so that further recursive<br>
invocations will copy the rest of the structure. In addition, it sets<br>
the swizzle field for the source register to an appropriate value of<br>
swizzle_for_size(...) for the size of each element being copied, so<br>
that later optimization passes won't be fooled into thinking that<br>
unused vector elements are live.<br>
<br>
This all works fine. However, emit_block_move also contains an<br>
assertion to verify, before setting the swizzle field for the source<br>
register, that the source register doesn't already contain a<br>
nontrivial swizzle. The intention is to make sure that the caller of<br>
emit_block_move hasn't already done some swizzling of the data before<br>
the call, which emit_block_move would then counteract when it<br>
overwrites the swizzle field. But the assertion is at the lowest<br>
level of nesting of emit_block_move, which means that after the first<br>
element is copied, instead of checking the swizzle field set by the<br>
caller, it checks the swizzle field used when moving the previous<br>
element. That means that if the structure contains elements of<br>
different vector sizes (which therefore require different swizzles),<br>
the assertion will erroneously fire.<br>
<br>
This patch moves the assertion from emit_block_move to the calling<br>
function, vec4_visitor::visit(ir_assignment *). Since the caller is<br>
non-recursive, the assertion will only happen once, and won't be<br>
fooled by emit_block_move's modification of the swizzle field.<br>
<br>
This patch also reverts commit fe006a7 (i965/vs: Fix swizzle related<br>
assertion), which attempted to fix the bug by making the assertion<br>
more lenient, but only worked properly for structures, arrays, and<br>
matrices in which each constituent vector is the same size.<br>
<br>
This fixes the problem described in comment 9 of<br>
<a href="https://bugs.freedesktop.org/show_bug.cgi?id=40865" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=40865</a>. Unfortunately, it<br>
doesn't fix the whole bug, since the test in question is also failing<br>
due to lack of register spilling support in the VS.<br>
<br>
Fixes piglit test fdo40865_c9. No piglit regressions on Sandy Bridge.<br>
<br>
Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=40865#c9" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=40865#c9</a><br></blockquote><div><br>I forgot to mention: This is a candidate for the 8.0 release branch.<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>
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 12 +++++++++---<br>
1 files changed, 9 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
index 5df2470..10b3c20 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
@@ -1532,9 +1532,6 @@ vec4_visitor::emit_block_move(dst_reg *dst, src_reg *src,<br>
<br>
dst->writemask = (1 << type->vector_elements) - 1;<br>
<br>
- /* Do we need to worry about swizzling a swizzle? */<br>
- assert(src->swizzle == BRW_SWIZZLE_NOOP<br>
- || src->swizzle == swizzle_for_size(type->vector_elements));<br>
src->swizzle = swizzle_for_size(type->vector_elements);<br>
<br>
vec4_instruction *inst = emit(MOV(*dst, *src));<br>
@@ -1617,6 +1614,15 @@ vec4_visitor::visit(ir_assignment *ir)<br>
emit_bool_to_cond_code(ir->condition, &predicate);<br>
}<br>
<br>
+ /* emit_block_move doesn't account for swizzles in the source register.<br>
+ * This should be ok, since the source register is a structure or an<br>
+ * array, and those can't be swizzled. But double-check to be sure.<br>
+ */<br>
+ assert(src.swizzle ==<br>
+ (ir->rhs->type->is_matrix()<br>
+ ? swizzle_for_size(ir->rhs->type->vector_elements)<br>
+ : BRW_SWIZZLE_NOOP));<br>
+<br>
emit_block_move(&dst, &src, ir->rhs->type, predicate);<br>
return;<br>
}<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.6.5<br>
<br>
</font></span></blockquote></div><br>