glsl: Add function support to glsl_to_nir
Based on a patch from Tim Arceri, but I had to substantially rewrite it as a result of the NIR derefs rework. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
@@ -100,6 +100,8 @@ private:
|
|||||||
/* whether the IR we're operating on is per-function or global */
|
/* whether the IR we're operating on is per-function or global */
|
||||||
bool is_global;
|
bool is_global;
|
||||||
|
|
||||||
|
ir_function_signature *sig;
|
||||||
|
|
||||||
/* map of ir_variable -> nir_variable */
|
/* map of ir_variable -> nir_variable */
|
||||||
struct hash_table *var_table;
|
struct hash_table *var_table;
|
||||||
|
|
||||||
@@ -292,6 +294,12 @@ nir_visitor::visit(ir_variable *ir)
|
|||||||
if (ir->data.mode == ir_var_shader_shared)
|
if (ir->data.mode == ir_var_shader_shared)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* FINISHME: inout parameters */
|
||||||
|
assert(ir->data.mode != ir_var_function_inout);
|
||||||
|
|
||||||
|
if (ir->data.mode == ir_var_function_out)
|
||||||
|
return;
|
||||||
|
|
||||||
nir_variable *var = rzalloc(shader, nir_variable);
|
nir_variable *var = rzalloc(shader, nir_variable);
|
||||||
var->type = ir->type;
|
var->type = ir->type;
|
||||||
var->name = ralloc_strdup(var, ir->name);
|
var->name = ralloc_strdup(var, ir->name);
|
||||||
@@ -316,8 +324,6 @@ nir_visitor::visit(ir_variable *ir)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ir_var_function_in:
|
case ir_var_function_in:
|
||||||
case ir_var_function_out:
|
|
||||||
case ir_var_function_inout:
|
|
||||||
case ir_var_const_in:
|
case ir_var_const_in:
|
||||||
var->data.mode = nir_var_function;
|
var->data.mode = nir_var_function;
|
||||||
break;
|
break;
|
||||||
@@ -473,8 +479,33 @@ nir_visitor::create_function(ir_function_signature *ir)
|
|||||||
|
|
||||||
nir_function *func = nir_function_create(shader, ir->function_name());
|
nir_function *func = nir_function_create(shader, ir->function_name());
|
||||||
|
|
||||||
assert(ir->parameters.is_empty());
|
func->num_params = ir->parameters.length() +
|
||||||
assert(ir->return_type == glsl_type::void_type);
|
(ir->return_type != glsl_type::void_type);
|
||||||
|
func->params = ralloc_array(shader, nir_parameter, func->num_params);
|
||||||
|
|
||||||
|
unsigned np = 0;
|
||||||
|
|
||||||
|
if (ir->return_type != glsl_type::void_type) {
|
||||||
|
/* The return value is a variable deref (basically an out parameter) */
|
||||||
|
func->params[np].num_components = 1;
|
||||||
|
func->params[np].bit_size = 32;
|
||||||
|
np++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach_in_list(ir_variable, param, &ir->parameters) {
|
||||||
|
/* FINISHME: pass arrays, structs, etc by reference? */
|
||||||
|
assert(param->type->is_vector() || param->type->is_scalar());
|
||||||
|
|
||||||
|
if (param->data.mode == ir_var_function_in) {
|
||||||
|
func->params[np].num_components = param->type->vector_elements;
|
||||||
|
func->params[np].bit_size = glsl_get_bit_size(param->type);
|
||||||
|
} else {
|
||||||
|
func->params[np].num_components = 1;
|
||||||
|
func->params[np].bit_size = 32;
|
||||||
|
}
|
||||||
|
np++;
|
||||||
|
}
|
||||||
|
assert(np == func->num_params);
|
||||||
|
|
||||||
_mesa_hash_table_insert(this->overload_table, ir, func);
|
_mesa_hash_table_insert(this->overload_table, ir, func);
|
||||||
}
|
}
|
||||||
@@ -492,6 +523,8 @@ nir_visitor::visit(ir_function_signature *ir)
|
|||||||
if (ir->is_intrinsic())
|
if (ir->is_intrinsic())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this->sig = ir;
|
||||||
|
|
||||||
struct hash_entry *entry =
|
struct hash_entry *entry =
|
||||||
_mesa_hash_table_search(this->overload_table, ir);
|
_mesa_hash_table_search(this->overload_table, ir);
|
||||||
|
|
||||||
@@ -502,13 +535,25 @@ nir_visitor::visit(ir_function_signature *ir)
|
|||||||
nir_function_impl *impl = nir_function_impl_create(func);
|
nir_function_impl *impl = nir_function_impl_create(func);
|
||||||
this->impl = impl;
|
this->impl = impl;
|
||||||
|
|
||||||
assert(strcmp(func->name, "main") == 0);
|
|
||||||
assert(ir->parameters.is_empty());
|
|
||||||
|
|
||||||
this->is_global = false;
|
this->is_global = false;
|
||||||
|
|
||||||
nir_builder_init(&b, impl);
|
nir_builder_init(&b, impl);
|
||||||
b.cursor = nir_after_cf_list(&impl->body);
|
b.cursor = nir_after_cf_list(&impl->body);
|
||||||
|
|
||||||
|
unsigned i = (ir->return_type != glsl_type::void_type) ? 1 : 0;
|
||||||
|
|
||||||
|
foreach_in_list(ir_variable, param, &ir->parameters) {
|
||||||
|
nir_variable *var =
|
||||||
|
nir_local_variable_create(impl, param->type, param->name);
|
||||||
|
|
||||||
|
if (param->data.mode == ir_var_function_in) {
|
||||||
|
nir_store_var(&b, var, nir_load_param(&b, i), ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mesa_hash_table_insert(var_table, param, var);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
visit_exec_list(&ir->body, this);
|
visit_exec_list(&ir->body, this);
|
||||||
|
|
||||||
this->is_global = true;
|
this->is_global = true;
|
||||||
@@ -598,7 +643,15 @@ nir_visitor::visit(ir_loop_jump *ir)
|
|||||||
void
|
void
|
||||||
nir_visitor::visit(ir_return *ir)
|
nir_visitor::visit(ir_return *ir)
|
||||||
{
|
{
|
||||||
assert(ir->value == NULL);
|
if (ir->value != NULL) {
|
||||||
|
nir_deref_instr *ret_deref =
|
||||||
|
nir_build_deref_cast(&b, nir_load_param(&b, 0),
|
||||||
|
nir_var_function, ir->value->type, 0);
|
||||||
|
|
||||||
|
nir_ssa_def *val = evaluate_rvalue(ir->value);
|
||||||
|
nir_store_deref(&b, ret_deref, val, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
|
nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
|
||||||
nir_builder_instr_insert(&b, &instr->instr);
|
nir_builder_instr_insert(&b, &instr->instr);
|
||||||
}
|
}
|
||||||
@@ -1253,7 +1306,47 @@ nir_visitor::visit(ir_call *ir)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable("glsl_to_nir only handles function calls to intrinsics");
|
struct hash_entry *entry =
|
||||||
|
_mesa_hash_table_search(this->overload_table, ir->callee);
|
||||||
|
assert(entry);
|
||||||
|
nir_function *callee = (nir_function *) entry->data;
|
||||||
|
|
||||||
|
nir_call_instr *call = nir_call_instr_create(this->shader, callee);
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
nir_deref_instr *ret_deref = NULL;
|
||||||
|
if (ir->return_deref) {
|
||||||
|
nir_variable *ret_tmp =
|
||||||
|
nir_local_variable_create(this->impl, ir->return_deref->type,
|
||||||
|
"return_tmp");
|
||||||
|
ret_deref = nir_build_deref_var(&b, ret_tmp);
|
||||||
|
call->params[i++] = nir_src_for_ssa(&ret_deref->dest.ssa);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach_two_lists(formal_node, &ir->callee->parameters,
|
||||||
|
actual_node, &ir->actual_parameters) {
|
||||||
|
ir_rvalue *param_rvalue = (ir_rvalue *) actual_node;
|
||||||
|
ir_variable *sig_param = (ir_variable *) formal_node;
|
||||||
|
|
||||||
|
if (sig_param->data.mode == ir_var_function_out) {
|
||||||
|
nir_deref_instr *out_deref = evaluate_deref(param_rvalue);
|
||||||
|
call->params[i] = nir_src_for_ssa(&out_deref->dest.ssa);
|
||||||
|
} else if (sig_param->data.mode == ir_var_function_in) {
|
||||||
|
nir_ssa_def *val = evaluate_rvalue(param_rvalue);
|
||||||
|
nir_src src = nir_src_for_ssa(val);
|
||||||
|
|
||||||
|
nir_src_copy(&call->params[i], &src, call);
|
||||||
|
} else if (sig_param->data.mode == ir_var_function_inout) {
|
||||||
|
unreachable("unimplemented: inout parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_builder_instr_insert(&b, &call->instr);
|
||||||
|
|
||||||
|
if (ir->return_deref)
|
||||||
|
nir_store_deref(&b, evaluate_deref(ir->return_deref), nir_load_deref(&b, ret_deref), ~0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2180,6 +2273,23 @@ nir_visitor::visit(ir_constant *ir)
|
|||||||
void
|
void
|
||||||
nir_visitor::visit(ir_dereference_variable *ir)
|
nir_visitor::visit(ir_dereference_variable *ir)
|
||||||
{
|
{
|
||||||
|
if (ir->variable_referenced()->data.mode == ir_var_function_out) {
|
||||||
|
unsigned i = (sig->return_type != glsl_type::void_type) ? 1 : 0;
|
||||||
|
|
||||||
|
foreach_in_list(ir_variable, param, &sig->parameters) {
|
||||||
|
if (param == ir->variable_referenced()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->deref = nir_build_deref_cast(&b, nir_load_param(&b, i),
|
||||||
|
nir_var_function, ir->type, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ir->variable_referenced()->data.mode != ir_var_function_inout);
|
||||||
|
|
||||||
struct hash_entry *entry =
|
struct hash_entry *entry =
|
||||||
_mesa_hash_table_search(this->var_table, ir->var);
|
_mesa_hash_table_search(this->var_table, ir->var);
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
Reference in New Issue
Block a user