glsl: propagate max_array_access through function calls

Fixes a bug where if an uniform array is passed to a function the accesses
to the array are not propagated so later all but the first vector of the
uniform array are removed in parcel_out_uniform_storage resulting in
broken shaders and out of bounds access to arrays in
brw::vec4_visitor::pack_uniform_registers.

Cc: mesa-stable@lists.freedesktop.org
Reviewed-and-Tested-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Dominik Behr <dbehr@chromium.org>
This commit is contained in:
Dominik Behr 2013-09-04 14:40:48 -07:00 committed by Matt Turner
parent 85f7df81a9
commit 0f6fce1585

View file

@ -173,6 +173,38 @@ public:
return visit_continue;
}
virtual ir_visitor_status visit_leave(ir_call *ir)
{
/* Traverse list of function parameters, and for array parameters
* propagate max_array_access. Otherwise arrays that are only referenced
* from inside functions via function parameters will be incorrectly
* optimized. This will lead to incorrect code being generated (or worse).
* Do it when leaving the node so the children would propagate their
* array accesses first.
*/
const exec_node *formal_param_node = ir->callee->parameters.get_head();
if (formal_param_node) {
const exec_node *actual_param_node = ir->actual_parameters.get_head();
while (!actual_param_node->is_tail_sentinel()) {
ir_variable *formal_param = (ir_variable *) formal_param_node;
ir_rvalue *actual_param = (ir_rvalue *) actual_param_node;
formal_param_node = formal_param_node->get_next();
actual_param_node = actual_param_node->get_next();
if (formal_param->type->is_array()) {
ir_dereference_variable *deref = actual_param->as_dereference_variable();
if (deref && deref->var && deref->var->type->is_array()) {
deref->var->max_array_access =
MAX2(formal_param->max_array_access, deref->var->max_array_access);
}
}
}
}
return visit_continue;
}
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
if (hash_table_find(locals, ir->var) == NULL) {