[Mesa-dev] [PATCH v4 2/2] glsl: fix interpolateAtXxx(some_vec[idx], ...) with dynamic idx

Nicolai Hähnle nhaehnle at gmail.com
Tue Oct 10 12:09:41 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

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.
---
 .../glsl/lower_vec_index_to_cond_assign.cpp        | 31 +++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

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
@@ -121,21 +121,50 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(void *mem_
 
    this->progress = true;
    return deref(var).val;
 }
 
 ir_rvalue *
 ir_vec_index_to_cond_assign_visitor::convert_vector_extract_to_cond_assign(ir_rvalue *ir)
 {
    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),
                                            expr->operands[0],
                                            expr->operands[1],
                                            ir->type);
 }
 
 ir_visitor_status
 ir_vec_index_to_cond_assign_visitor::visit_enter(ir_expression *ir)
-- 
2.11.0



More information about the mesa-dev mailing list