From 4f42450b86ea30f9228309e02ca68755c389866f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nicolai=20H=C3=A4hnle?= Date: Wed, 14 Jun 2017 12:43:10 +0200 Subject: [PATCH] glsl: allow any l-value of an input variable as interpolant in interpolateAt* The intended rule has been clarified in GLSL 4.60, Section 8.13.2 (Interpolation Functions): "For all of the interpolation functions, interpolant must be an l-value from an in declaration; this can include a variable, a block or structure member, an array element, or some combination of these. Component selection operators (e.g., .xy) may be used when specifying interpolant." For members of interface blocks, var->data.must_be_shader_input must be determined on-the-fly after lowering interface blocks, since we don't want to disable varying packing for an entire block just because one input in it is used in interpolateAt*. v2: keep setting must_be_shader_input in ast_function (Ian) v3: follow the relaxed rule of GLSL 4.60 v4: only apply the relaxed rules to desktop GL (the ES WG decided that the relaxed rules may apply in a future version but not retroactively; see also dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_centroid.negative.*) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101378 Reviewed-by: Ian Romanick (v1) Reviewed-by: Timothy Arceri --- src/compiler/glsl/ast_function.cpp | 19 ++++++++++++++----- .../glsl/lower_named_interface_blocks.cpp | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp index 46a61e46fd5..d1596c272e6 100644 --- a/src/compiler/glsl/ast_function.cpp +++ b/src/compiler/glsl/ast_function.cpp @@ -227,19 +227,28 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, val = ((ir_swizzle *)val)->val; } - while (val->ir_type == ir_type_dereference_array) { - val = ((ir_dereference_array *)val)->array; + for (;;) { + if (val->ir_type == ir_type_dereference_array) { + val = ((ir_dereference_array *)val)->array; + } else if (val->ir_type == ir_type_dereference_record && + !state->es_shader) { + val = ((ir_dereference_record *)val)->record; + } else + break; } - if (!val->as_dereference_variable() || - val->variable_referenced()->data.mode != ir_var_shader_in) { + ir_variable *var = NULL; + if (const ir_dereference_variable *deref_var = val->as_dereference_variable()) + var = deref_var->variable_referenced(); + + if (!var || var->data.mode != ir_var_shader_in) { _mesa_glsl_error(&loc, state, "parameter `%s` must be a shader input", formal->name); return false; } - val->variable_referenced()->data.must_be_shader_input = 1; + var->data.must_be_shader_input = 1; } /* Verify that 'out' and 'inout' actual parameters are lvalues. */ diff --git a/src/compiler/glsl/lower_named_interface_blocks.cpp b/src/compiler/glsl/lower_named_interface_blocks.cpp index 064694128bf..136352a131b 100644 --- a/src/compiler/glsl/lower_named_interface_blocks.cpp +++ b/src/compiler/glsl/lower_named_interface_blocks.cpp @@ -115,6 +115,7 @@ public: void run(exec_list *instructions); virtual ir_visitor_status visit_leave(ir_assignment *); + virtual ir_visitor_status visit_leave(ir_expression *); virtual void handle_rvalue(ir_rvalue **rvalue); }; @@ -238,6 +239,23 @@ flatten_named_interface_blocks_declarations::visit_leave(ir_assignment *ir) return rvalue_visit(ir); } +ir_visitor_status +flatten_named_interface_blocks_declarations::visit_leave(ir_expression *ir) +{ + ir_visitor_status status = rvalue_visit(ir); + + if (ir->operation == ir_unop_interpolate_at_centroid || + ir->operation == ir_binop_interpolate_at_offset || + ir->operation == ir_binop_interpolate_at_sample) { + const ir_rvalue *val = ir->operands[0]; + + /* This disables varying packing for this input. */ + val->variable_referenced()->data.must_be_shader_input = 1; + } + + return status; +} + void flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue) { -- 2.30.2