From 79b8b42081a6d4e219350882316bdc971c68ceec Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 18 Dec 2015 15:07:16 -0800 Subject: [PATCH] nir/spirv: Handle function calls --- src/glsl/nir/spirv_to_nir.c | 86 +++++++++++++++++++++++++++-- src/glsl/nir/spirv_to_nir_private.h | 5 +- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/glsl/nir/spirv_to_nir.c b/src/glsl/nir/spirv_to_nir.c index 07d47891770..d56f9be4447 100644 --- a/src/glsl/nir/spirv_to_nir.c +++ b/src/glsl/nir/spirv_to_nir.c @@ -1819,7 +1819,44 @@ static void vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) { - unreachable("Unhandled opcode"); + struct nir_function_overload *overload = + vtn_value(b, w[3], vtn_value_type_function)->func->impl->overload; + + nir_call_instr *call = nir_call_instr_create(b->nb.shader, overload); + for (unsigned i = 0; i < call->num_params; i++) { + unsigned arg_id = w[4 + i]; + struct vtn_value *arg = vtn_untyped_value(b, arg_id); + if (arg->value_type == vtn_value_type_deref) { + call->params[i] = + nir_deref_as_var(nir_copy_deref(call, &arg->deref->deref)); + } else { + struct vtn_ssa_value *arg_ssa = vtn_ssa_value(b, arg_id); + + /* Make a temporary to store the argument in */ + nir_variable *tmp = + nir_local_variable_create(b->impl, arg_ssa->type, "arg_tmp"); + call->params[i] = nir_deref_var_create(call, tmp); + + vtn_variable_store(b, arg_ssa, call->params[i], arg->type); + } + } + + nir_variable *out_tmp = NULL; + if (!glsl_type_is_void(overload->return_type)) { + out_tmp = nir_local_variable_create(b->impl, overload->return_type, + "out_tmp"); + call->return_deref = nir_deref_var_create(call, out_tmp); + } + + nir_builder_instr_insert(&b->nb, &call->instr); + + if (glsl_type_is_void(overload->return_type)) { + vtn_push_value(b, w[2], vtn_value_type_undef); + } else { + struct vtn_type *rettype = vtn_value(b, w[1], vtn_value_type_type)->type; + struct vtn_value *retval = vtn_push_value(b, w[2], vtn_value_type_ssa); + retval->ssa = vtn_variable_load(b, call->return_deref, rettype); + } } static struct vtn_ssa_value * @@ -3260,6 +3297,8 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode, const struct glsl_type *result_type = vtn_value(b, w[1], vtn_value_type_type)->type->type; struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function); + val->func = b->func; + const struct glsl_type *func_type = vtn_value(b, w[4], vtn_value_type_type)->type->type; @@ -3290,7 +3329,17 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode, } } } - b->func->overload = overload; + + overload->return_type = glsl_get_function_return_type(func_type); + + b->func->impl = nir_function_impl_create(overload); + if (!glsl_type_is_void(overload->return_type)) { + b->func->impl->return_var = + nir_local_variable_create(b->func->impl, + overload->return_type, "retval"); + } + + b->func_param_idx = 0; break; } @@ -3299,8 +3348,22 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode, b->func = NULL; break; - case SpvOpFunctionParameter: - break; /* Does nothing */ + case SpvOpFunctionParameter: { + struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_deref); + + assert(b->func_param_idx < b->func->impl->num_params); + unsigned idx = b->func_param_idx++; + + nir_variable *param = + nir_local_variable_create(b->func->impl, + b->func->impl->overload->params[idx].type, + val->name); + + b->func->impl->params[idx] = param; + val->deref = nir_deref_var_create(b, param); + val->deref_type = vtn_value(b, w[1], vtn_value_type_type)->type; + break; + } case SpvOpLabel: { assert(b->block == NULL); @@ -3723,6 +3786,18 @@ vtn_walk_blocks(struct vtn_builder *b, struct vtn_block *start, return; } + case SpvOpReturnValue: { + struct vtn_ssa_value *src = vtn_ssa_value(b, w[1]); + vtn_variable_store(b, src, + nir_deref_var_create(b, b->impl->return_var), + NULL); + + nir_jump_instr *jump = nir_jump_instr_create(b->shader, + nir_jump_return); + nir_builder_instr_insert(&b->nb, &jump->instr); + return; + } + case SpvOpKill: { nir_intrinsic_instr *discard = nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard); @@ -3731,7 +3806,6 @@ vtn_walk_blocks(struct vtn_builder *b, struct vtn_block *start, } case SpvOpSwitch: - case SpvOpReturnValue: case SpvOpUnreachable: default: unreachable("Unhandled opcode"); @@ -3781,7 +3855,7 @@ spirv_to_nir(const uint32_t *words, size_t word_count, vtn_handle_first_cfg_pass_instruction); foreach_list_typed(struct vtn_function, func, node, &b->functions) { - b->impl = nir_function_impl_create(func->overload); + b->impl = func->impl; b->const_table = _mesa_hash_table_create(b, _mesa_hash_pointer, _mesa_key_pointer_equal); b->block_table = _mesa_hash_table_create(b, _mesa_hash_pointer, diff --git a/src/glsl/nir/spirv_to_nir_private.h b/src/glsl/nir/spirv_to_nir_private.h index 40f0c78ae78..edc3461b846 100644 --- a/src/glsl/nir/spirv_to_nir_private.h +++ b/src/glsl/nir/spirv_to_nir_private.h @@ -61,7 +61,7 @@ struct vtn_block { struct vtn_function { struct exec_node node; - nir_function_overload *overload; + nir_function_impl *impl; struct vtn_block *start_block; const uint32_t *end; @@ -204,6 +204,9 @@ struct vtn_builder { struct vtn_function *func; struct exec_list functions; + + /* Current function parameter index */ + unsigned func_param_idx; }; static inline struct vtn_value * -- 2.30.2