summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNicolai Hähnle <[email protected]>2017-08-01 12:44:34 +0200
committerNicolai Hähnle <[email protected]>2017-11-03 14:30:08 +0100
commitca63a5ed3e9efb2bd645b425f7393089f4e132a6 (patch)
treed088b1dfc76ec62ee3d2fffbe181cecf7e05c743 /src
parent4f42450b86ea30f9228309e02ca68755c389866f (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 <[email protected]>
Diffstat (limited to 'src')
-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),