summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2015-12-18 15:07:16 -0800
committerJason Ekstrand <jason.ekstrand@intel.com>2015-12-23 13:49:56 -0800
commit79b8b42081a6d4e219350882316bdc971c68ceec (patch)
tree31e9e1539b846e07c99bc64d32438c14539e2c6c /src
parent95990c96cccede9777e0552beffdf2bd4b494a04 (diff)
downloadexternal_mesa3d-79b8b42081a6d4e219350882316bdc971c68ceec.zip
external_mesa3d-79b8b42081a6d4e219350882316bdc971c68ceec.tar.gz
external_mesa3d-79b8b42081a6d4e219350882316bdc971c68ceec.tar.bz2
nir/spirv: Handle function calls
Diffstat (limited to 'src')
-rw-r--r--src/glsl/nir/spirv_to_nir.c86
-rw-r--r--src/glsl/nir/spirv_to_nir_private.h5
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 07d4789..d56f9be 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 40f0c78..edc3461 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 *