On 20 January 2012 16:12, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.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="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'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_<u></u>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/<u></u>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/<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->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_<u></u>elements));<br>
src->swizzle = swizzle_for_size(type->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-><u></u>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-><u></u>type->vector_elements)<br>
+ : BRW_SWIZZLE_NOOP));<br>
+<br></div></div>
emit_block_move(&dst,&src, ir->rhs->type, predicate);<br>
return;<br>
}<br>
</blockquote>
<br>
I'm not really convinced that this assertion is useful. I'd just remove it.<br></blockquote><div><br>I can vaguely imagine some future scenario where we accidentally swizzle something we're not supposed to, and this assertion might make it easier to notice the bug if we do. So I'd like to err on the side of leaving it in for now if it's all the same to you. But if it causes any further trouble I'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 <<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>><br>
</blockquote></div><br>