From 444a621e55044f4d44efb98b76cb4ce1bde47da4 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Fri, 22 Nov 2013 12:37:22 -0800 Subject: glsl: Fix lowering of direct assignment in lower_clip_distance. In commit 065da16 (glsl: Convert lower_clip_distance_visitor to be an ir_rvalue_visitor), we failed to notice that since lower_clip_distance_visitor overrides visit_leave(ir_assignment *), ir_rvalue_visitor::visit_leave(ir_assignment *) wasn't getting called. As a result, clip distance dereferences appearing directly on the right hand side of an assignment (not in a subexpression) weren't getting properly lowered. This caused an ir_dereference_variable node to be left in the IR that referred to the old gl_ClipDistance variable. However, since the lowering pass replaces gl_ClipDistance with gl_ClipDistanceMESA, this turned into a dangling pointer when the IR got reparented. Prior to the introduction of geometry shaders, this bug was unlikely to arise, because (a) reading from gl_ClipDistance[i] in the fragment shader was rare, and (b) when it happened, it was likely that it would either appear in a subexpression, or be hoisted into a subexpression by tree grafting. However, in a geometry shader, we're likely to see a statement like this, which would trigger the bug: gl_ClipDistance[i] = gl_in[j].gl_ClipDistance[i]; This patch causes lower_clip_distance_visitor::visit_leave(ir_assignment *) to call the base class visitor, so that the right hand side of the assignment is properly lowered. Fixes piglit test: - spec/glsl-1.50/execution/geometry/clip-distance-itemized-copy Cc: Ian Romanick Cc: "9.2" Cc: "10.0" Reviewed-by: Eric Anholt Reviewed-by: Ian Romanick (cherry picked from commit 9dfcb05fa649ee7a573eab3d16851ebd4cb96010) --- src/glsl/lower_clip_distance.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/glsl/lower_clip_distance.cpp b/src/glsl/lower_clip_distance.cpp index 682c8fdcd3e..04fa6d4108a 100644 --- a/src/glsl/lower_clip_distance.cpp +++ b/src/glsl/lower_clip_distance.cpp @@ -381,6 +381,11 @@ lower_clip_distance_visitor::fix_lhs(ir_assignment *ir) ir_visitor_status lower_clip_distance_visitor::visit_leave(ir_assignment *ir) { + /* First invoke the base class visitor. This causes handle_rvalue() to be + * called on ir->rhs and ir->condition. + */ + ir_rvalue_visitor::visit_leave(ir); + if (this->is_clip_distance_vec8(ir->lhs) || this->is_clip_distance_vec8(ir->rhs)) { /* LHS or RHS of the assignment is the entire 1D gl_ClipDistance array -- cgit v1.2.3