* main() function to copy the final values to the actual shader outputs.
*/
+namespace {
+
class output_read_remover : public ir_hierarchical_visitor {
protected:
/**
* A hash table mapping from the original ir_variable shader outputs
- * (ir_var_out mode) to the new temporaries to be used instead.
+ * (ir_var_shader_out mode) to the new temporaries to be used instead.
*/
hash_table *replacements;
void *mem_ctx;
+
+ unsigned stage;
public:
- output_read_remover();
+ output_read_remover(unsigned stage);
~output_read_remover();
virtual ir_visitor_status visit(class ir_dereference_variable *);
+ virtual ir_visitor_status visit_leave(class ir_emit_vertex *);
virtual ir_visitor_status visit_leave(class ir_return *);
virtual ir_visitor_status visit_leave(class ir_function_signature *);
};
+} /* anonymous namespace */
+
/**
* Hash function for the output variables - computes the hash of the name.
* NOTE: We're using the name string to ensure that the hash doesn't depend
return hash_table_string_hash(var->name);
}
-output_read_remover::output_read_remover()
+output_read_remover::output_read_remover(unsigned stage)
{
+ this->stage = stage;
mem_ctx = ralloc_context(NULL);
replacements =
hash_table_ctor(0, hash_table_var_hash, hash_table_pointer_compare);
ir_visitor_status
output_read_remover::visit(ir_dereference_variable *ir)
{
- if (ir->var->mode != ir_var_out)
+ if (ir->var->data.mode != ir_var_shader_out)
+ return visit_continue;
+ if (stage == MESA_SHADER_TESS_CTRL)
return visit_continue;
ir_variable *temp = (ir_variable *) hash_table_find(replacements, ir->var);
temp = new(var_ctx) ir_variable(ir->var->type, ir->var->name,
ir_var_temporary);
hash_table_insert(replacements, temp, ir->var);
+ ir->var->insert_after(temp);
}
/* Update the dereference to use the temporary */
return new(ctx) ir_assignment(lhs, rhs);
}
-/** Insert a copy-back assignment before a "return" statement */
+/** Insert a copy-back assignment before a "return" statement or a call to
+ * EmitVertex().
+ */
static void
emit_return_copy(const void *key, void *data, void *closure)
{
return visit_continue;
}
+ir_visitor_status
+output_read_remover::visit_leave(ir_emit_vertex *ir)
+{
+ hash_table_call_foreach(replacements, emit_return_copy, ir);
+ hash_table_clear(replacements);
+ return visit_continue;
+}
+
ir_visitor_status
output_read_remover::visit_leave(ir_function_signature *sig)
{
}
void
-lower_output_reads(exec_list *instructions)
+lower_output_reads(unsigned stage, exec_list *instructions)
{
- output_read_remover v;
+ output_read_remover v(stage);
visit_list_elements(&v, instructions);
}