summaryrefslogtreecommitdiffstats
path: root/src/glsl/opt_copy_propagation_elements.cpp
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2012-01-09 13:30:55 -0800
committerEric Anholt <eric@anholt.net>2012-01-10 16:44:16 -0800
commit057f9ae54b5efb0020cc0c049d50e778de3f3f7a (patch)
treeb18581e837e3cf54f0f0ed061ef121393c0a0d89 /src/glsl/opt_copy_propagation_elements.cpp
parent254b24f19511014cdf4741b73d69349ac9e931a2 (diff)
downloadexternal_mesa3d-057f9ae54b5efb0020cc0c049d50e778de3f3f7a.zip
external_mesa3d-057f9ae54b5efb0020cc0c049d50e778de3f3f7a.tar.gz
external_mesa3d-057f9ae54b5efb0020cc0c049d50e778de3f3f7a.tar.bz2
glsl: Fix copy_propagation_elements bug in handling self-copies.
We were doing the kill of the updated channels, then adding our copy to the list of available stuff to copy. But if the copy was updating its own source channels, we didn't notice, breaking this code: R0.xyzw = arg0 + arg1; R0.xyzw = R0.wwwx; gl_FragColor.xyzw = clamp(R0.xyzw, 0.0, 1.0); Fixes piglit glsl-copy-propagation-self-2. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/glsl/opt_copy_propagation_elements.cpp')
-rw-r--r--src/glsl/opt_copy_propagation_elements.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp
index be446bc..ebfd4fd 100644
--- a/src/glsl/opt_copy_propagation_elements.cpp
+++ b/src/glsl/opt_copy_propagation_elements.cpp
@@ -461,7 +461,20 @@ ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
swizzle[i] = orig_swizzle[j++];
}
- entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
+ int write_mask = ir->write_mask;
+ if (lhs->var == rhs->var) {
+ /* If this is a copy from the variable to itself, then we need
+ * to be sure not to include the updated channels from this
+ * instruction in the set of new source channels to be
+ * copy-propagated from.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (ir->write_mask & (1 << orig_swizzle[i]))
+ write_mask &= ~(1 << i);
+ }
+ }
+
+ entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, write_mask,
swizzle);
this->acp->push_tail(entry);
}