[Mesa-dev] [PATCH] glsl: propagate max_array_access through function calls
Ian Romanick
idr at freedesktop.org
Tue Aug 27 08:26:47 PDT 2013
On 08/21/2013 05:57 PM, Dominik Behr wrote:
> 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.
>
> Signed-off-by: Dominik Behr <dbehr at chromium.org>
> ---
> src/glsl/link_functions.cpp | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
> index 6b3e154..32e2012 100644
> --- a/src/glsl/link_functions.cpp
> +++ b/src/glsl/link_functions.cpp
> @@ -173,6 +173,32 @@ 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, do it when leaving the node
> + so the childen would propagate their array accesses first */
children
I also think this comment should be expanded. On the first read of this
code, it wasn't obvious to me why this was necessary. It's worth
mentioning that the important case is when the reference to the array at
the call site does not reference a specific element. In that case the
access range of the from the callee is propagated back to the array
passed in.
> + exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
> + exec_list_iterator param_iter = ir->actual_parameters.iterator();
While iterators are a fine design pattern, the implementation of them in
the compiler front-end is garbage (and I made that implementation). We
stopped writing new code to use the iterators years ago. There is other
code that does a similar double-walk of the signature parameters and
actual parameters lists.
I think the best example is in
lower_clip_distance_visitor::visit_leave(ir_call *ir) in
lower_clip_distance.cpp.
> + while (param_iter.has_next()) {
> + ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
> + ir_rvalue *param = (ir_rvalue *) param_iter.get();
> + assert(sig_param);
> + assert(param);
> + if (sig_param->type->is_array()) {
> + ir_dereference_variable *deref = param->as_dereference_variable();
> + if (deref && deref->var && deref->var->type->is_array()) {
> + if (sig_param->max_array_access > deref->var->max_array_access) {
> + deref->var->max_array_access = sig_param->max_array_access;
> + }
This should end up looking more similar to the code in
call_link_visitor::visit(ir_dereference_variable *ir) around line 200
(without your patch).
var->max_array_access =
MAX2(var->max_array_access, ir->var->max_array_access);
> + }
> + }
> + sig_param_iter.next();
> + param_iter.next();
> + }
> + return visit_continue;
> + }
> +
> virtual ir_visitor_status visit(ir_dereference_variable *ir)
> {
> if (hash_table_find(locals, ir->var) == NULL) {
>
More information about the mesa-dev
mailing list