summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorRhys Perry <[email protected]>2018-06-06 20:55:08 +0100
committerMarek Olšák <[email protected]>2018-08-01 00:10:01 -0400
commitbd56e117ff8c4565388717cdfd30cf256c71c6cf (patch)
treecb97b3812c59653add4e7bd880eae0834bfbbd60 /src/compiler
parentf903bce8a649296f9d8a67a740942b2a80303c50 (diff)
glsl: fix function inlining with opaque parameters
Signed-off-by: Rhys Perry <[email protected]> Reviewed-by: Marek Olšák <[email protected]> Signed-off-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/glsl/opt_function_inlining.cpp52
1 files changed, 44 insertions, 8 deletions
diff --git a/src/compiler/glsl/opt_function_inlining.cpp b/src/compiler/glsl/opt_function_inlining.cpp
index 04690b6cf45..52f57da936d 100644
--- a/src/compiler/glsl/opt_function_inlining.cpp
+++ b/src/compiler/glsl/opt_function_inlining.cpp
@@ -131,6 +131,18 @@ ir_save_lvalue_visitor::visit_enter(ir_dereference_array *deref)
return visit_stop;
}
+static bool
+should_replace_variable(ir_variable *sig_param, ir_rvalue *param) {
+ /* For opaque types, we want the inlined variable references
+ * referencing the passed in variable, since that will have
+ * the location information, which an assignment of an opaque
+ * variable wouldn't.
+ */
+ return sig_param->type->contains_opaque() &&
+ param->is_dereference() &&
+ sig_param->data.mode == ir_var_function_in;
+}
+
void
ir_call::generate_inline(ir_instruction *next_ir)
{
@@ -155,12 +167,8 @@ ir_call::generate_inline(ir_instruction *next_ir)
ir_rvalue *param = (ir_rvalue *) actual_node;
/* Generate a new variable for the parameter. */
- if (sig_param->type->contains_opaque()) {
- /* For opaque types, we want the inlined variable references
- * referencing the passed in variable, since that will have
- * the location information, which an assignment of an opaque
- * variable wouldn't. Fix it up below.
- */
+ if (should_replace_variable(sig_param, param)) {
+ /* Actual replacement happens below */
parameters[i] = NULL;
} else {
parameters[i] = sig_param->clone(ctx, ht);
@@ -242,10 +250,9 @@ ir_call::generate_inline(ir_instruction *next_ir)
ir_rvalue *const param = (ir_rvalue *) actual_node;
ir_variable *sig_param = (ir_variable *) formal_node;
- if (sig_param->type->contains_opaque()) {
+ if (should_replace_variable(sig_param, param)) {
ir_dereference *deref = param->as_dereference();
- assert(deref);
do_variable_replacement(&new_instructions, sig_param, deref);
}
}
@@ -351,6 +358,9 @@ public:
virtual ir_visitor_status visit_leave(ir_dereference_array *);
virtual ir_visitor_status visit_leave(ir_dereference_record *);
virtual ir_visitor_status visit_leave(ir_texture *);
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+ virtual ir_visitor_status visit_leave(ir_expression *);
+ virtual ir_visitor_status visit_leave(ir_return *);
void replace_deref(ir_dereference **deref);
void replace_rvalue(ir_rvalue **rvalue);
@@ -392,6 +402,32 @@ ir_variable_replacement_visitor::visit_leave(ir_texture *ir)
}
ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_assignment *ir)
+{
+ replace_deref(&ir->lhs);
+ replace_rvalue(&ir->rhs);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_expression *ir)
+{
+ for (uint8_t i = 0; i < ir->num_operands; i++)
+ replace_rvalue(&ir->operands[i]);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_return *ir)
+{
+ replace_rvalue(&ir->value);
+
+ return visit_continue;
+}
+
+ir_visitor_status
ir_variable_replacement_visitor::visit_leave(ir_dereference_array *ir)
{
replace_rvalue(&ir->array);