summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-08-01 12:44:34 +0200
committerEmil Velikov <emil.l.velikov@gmail.com>2017-11-29 19:42:26 +0000
commitb79e15b08699ecf8d2f67eecff46f1c8b7d9b577 (patch)
treeb35a9a479cfc01efcaee66fe401787e8df7c23fd
parent77cba992c39de3f5dfb76f1b93dc0d77f3bc8a04 (diff)
glsl: fix interpolateAtXxx(some_vec[idx], ...) with dynamic idx
The dynamic index of a vector (not array!) is lowered to a sequence of conditional assignments. However, the interpolate_at_* expressions require that the interpolant is an l-value of a shader input. So instead of doing conditional assignments of parts of the shader input and then interpolating that (which is nonsensical), we interpolate the entire shader input and then do conditional assignments of the interpolated result. Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> (cherry picked from commit ca63a5ed3e9efb2bd645b425f7393089f4e132a6)
-rw-r--r--src/compiler/glsl/lower_vec_index_to_cond_assign.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp b/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp
index a26253998e0..89244266602 100644
--- a/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp
+++ b/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp
@@ -128,7 +128,36 @@ ir_vec_index_to_cond_assign_visitor::convert_vector_extract_to_cond_assign(ir_rv
{
ir_expression *const expr = ir->as_expression();
- if (expr == NULL || expr->operation != ir_binop_vector_extract)
+ if (expr == NULL)
+ return ir;
+
+ if (expr->operation == ir_unop_interpolate_at_centroid ||
+ expr->operation == ir_binop_interpolate_at_offset ||
+ expr->operation == ir_binop_interpolate_at_sample) {
+ /* Lower interpolateAtXxx(some_vec[idx], ...) to
+ * interpolateAtXxx(some_vec, ...)[idx] before lowering to conditional
+ * assignments, to maintain the rule that the interpolant is an l-value
+ * referring to a (part of a) shader input.
+ *
+ * This is required when idx is dynamic (otherwise it gets lowered to
+ * a swizzle).
+ */
+ ir_expression *const interpolant = expr->operands[0]->as_expression();
+ if (!interpolant || interpolant->operation != ir_binop_vector_extract)
+ return ir;
+
+ ir_rvalue *vec_input = interpolant->operands[0];
+ ir_expression *const vec_interpolate =
+ new(base_ir) ir_expression(expr->operation, vec_input->type,
+ vec_input, expr->operands[1]);
+
+ return convert_vec_index_to_cond_assign(ralloc_parent(ir),
+ vec_interpolate,
+ interpolant->operands[1],
+ ir->type);
+ }
+
+ if (expr->operation != ir_binop_vector_extract)
return ir;
return convert_vec_index_to_cond_assign(ralloc_parent(ir),