On 19 January 2012 18:28, Paul Berry <span dir="ltr">&lt;<a href="mailto:stereotype441@gmail.com">stereotype441@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">
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&#39;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&#39;t already contain a<br>
nontrivial swizzle.  The intention is to make sure that the caller of<br>
emit_block_move hasn&#39;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&#39;t be<br>
fooled by emit_block_move&#39;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&#39;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-&gt;writemask = (1 &lt;&lt; type-&gt;vector_elements) - 1;<br>
<br>
-   /* Do we need to worry about swizzling a swizzle? */<br>
-   assert(src-&gt;swizzle == BRW_SWIZZLE_NOOP<br>
-         || src-&gt;swizzle == swizzle_for_size(type-&gt;vector_elements));<br>
    src-&gt;swizzle = swizzle_for_size(type-&gt;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-&gt;condition, &amp;predicate);<br>
       }<br>
<br>
+      /* emit_block_move doesn&#39;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&#39;t be swizzled.  But double-check to be sure.<br>
+       */<br>
+      assert(src.swizzle ==<br>
+             (ir-&gt;rhs-&gt;type-&gt;is_matrix()<br>
+              ? swizzle_for_size(ir-&gt;rhs-&gt;type-&gt;vector_elements)<br>
+              : BRW_SWIZZLE_NOOP));<br>
+<br>
       emit_block_move(&amp;dst, &amp;src, ir-&gt;rhs-&gt;type, predicate);<br>
       return;<br>
    }<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.6.5<br>
<br>
</font></span></blockquote></div><br>