diff options
author | Ilia Mirkin <[email protected]> | 2018-10-05 02:18:20 -0400 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2018-10-08 14:29:14 -0400 |
commit | 1bb1c03d618a9636563cf4dcf067876e50ba0d81 (patch) | |
tree | e629e3377b628c65608f3fbad7c1d2adb821da15 /src | |
parent | d3682766f66b69ab636a2b9ca74db48fab68e024 (diff) |
glsl: fix array assignments of a swizzled vector
This happens in situations where we might do
vec.wzyx[i] = ...
The swizzle would get effectively ignored because of the interaction
between how ir_assignment->set_lhs works and overwriting the write_mask.
There are two cases, one where i is a constant, and another where i is
variable. We have to be extra-careful in both cases.
Fixes the following WebGL test:
https://www.khronos.org/registry/webgl/sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
And the new piglit tests:
swizzled-writemask-indexing-nonconst.shader_test
swizzled-writemask-indexing.shader_test
Signed-off-by: Ilia Mirkin <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Cc: [email protected]
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/glsl/lower_vector_derefs.cpp | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/src/compiler/glsl/lower_vector_derefs.cpp b/src/compiler/glsl/lower_vector_derefs.cpp index 7583d1fdd3e..6cd9a2d819a 100644 --- a/src/compiler/glsl/lower_vector_derefs.cpp +++ b/src/compiler/glsl/lower_vector_derefs.cpp @@ -59,8 +59,7 @@ vector_deref_visitor::visit_enter(ir_assignment *ir) if (!deref->array->type->is_vector()) return ir_rvalue_enter_visitor::visit_enter(ir); - ir_dereference *const new_lhs = (ir_dereference *) deref->array; - ir->set_lhs(new_lhs); + ir_rvalue *const new_lhs = deref->array; void *mem_ctx = ralloc_parent(ir); ir_constant *old_index_constant = @@ -72,8 +71,16 @@ vector_deref_visitor::visit_enter(ir_assignment *ir) ir->rhs, deref->array_index); ir->write_mask = (1 << new_lhs->type->vector_elements) - 1; + ir->set_lhs(new_lhs); + } else if (new_lhs->ir_type != ir_type_swizzle) { + ir->set_lhs(new_lhs); + ir->write_mask = 1 << old_index_constant->get_uint_component(0); } else { - ir->write_mask = 1 << old_index_constant->get_int_component(0); + /* If the "new" LHS is a swizzle, use the set_lhs helper to instead + * swizzle the RHS. + */ + unsigned component[1] = { old_index_constant->get_uint_component(0) }; + ir->set_lhs(new(mem_ctx) ir_swizzle(new_lhs, component, 1)); } return ir_rvalue_enter_visitor::visit_enter(ir); |