On 20 January 2012 16:12, Kenneth Graunke <span dir="ltr">&lt;<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</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">
<div class="HOEnZb"><div class="h5">On 01/19/2012 06:28 PM, Paul Berry wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
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_<u></u>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/<u></u>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/<u></u>show_bug.cgi?id=40865#c9</a><br>
---<br>
  src/mesa/drivers/dri/i965/brw_<u></u>vec4_visitor.cpp |   12 +++++++++---<br>
  1 files changed, 9 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/<u></u>brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/<u></u>brw_vec4_visitor.cpp<br>
index 5df2470..10b3c20 100644<br>
--- a/src/mesa/drivers/dri/i965/<u></u>brw_vec4_visitor.cpp<br>
+++ b/src/mesa/drivers/dri/i965/<u></u>brw_vec4_visitor.cpp<br>
@@ -1532,9 +1532,6 @@ vec4_visitor::emit_block_move(<u></u>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_<u></u>elements));<br>
     src-&gt;swizzle = swizzle_for_size(type-&gt;vector_<u></u>elements);<br>
<br>
     vec4_instruction *inst = emit(MOV(*dst, *src));<br>
@@ -1617,6 +1614,15 @@ vec4_visitor::visit(ir_<u></u>assignment *ir)<br>
         emit_bool_to_cond_code(ir-&gt;<u></u>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;<u></u>type-&gt;vector_elements)<br>
+              : BRW_SWIZZLE_NOOP));<br>
+<br></div></div>
        emit_block_move(&amp;dst,&amp;src, ir-&gt;rhs-&gt;type, predicate);<br>
        return;<br>
     }<br>
</blockquote>
<br>
I&#39;m not really convinced that this assertion is useful.  I&#39;d just remove it.<br></blockquote><div><br>I can vaguely imagine some future scenario where we accidentally swizzle something we&#39;re not supposed to, and this assertion might make it easier to notice the bug if we do.  So I&#39;d like to err on the side of leaving it in for now if it&#39;s all the same to you.  But if it causes any further trouble I&#39;ll happily nuke it :)<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>
Either way:<br>
Reviewed-by: Kenneth Graunke &lt;<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>&gt;<br>
</blockquote></div><br>