mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 07:00:12 +01:00
vtn: handle struct kernel arguments passed by value
Due to LLVM ABI reasons the SPIRV-LLVM-Translator always uses pointers to private memory for struct function parameters. This includes kernel entry points. However technically it's also legal to pass those parameters by value according to the OpenCL SPIR-V Env spec. One compiler making use of this is e.g. artic based on Thorin. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12149 Cc: mesa-stable Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32141>
This commit is contained in:
parent
237ed6fd08
commit
d0560f59ce
1 changed files with 39 additions and 4 deletions
|
|
@ -6778,6 +6778,27 @@ vtn_create_builder(const uint32_t *words, size_t word_count,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See glsl_type_add_to_function_params and vtn_ssa_value_add_to_call_params */
|
||||||
|
static void
|
||||||
|
vtn_emit_kernel_entry_point_wrapper_struct_param(struct nir_builder *b,
|
||||||
|
nir_deref_instr *deref,
|
||||||
|
nir_call_instr *call,
|
||||||
|
unsigned *idx)
|
||||||
|
{
|
||||||
|
if (glsl_type_is_vector_or_scalar(deref->type)) {
|
||||||
|
call->params[(*idx)++] = nir_src_for_ssa(nir_load_deref(b, deref));
|
||||||
|
} else {
|
||||||
|
unsigned elems = glsl_get_length(deref->type);
|
||||||
|
for (unsigned i = 0; i < elems; i++) {
|
||||||
|
nir_deref_instr *child_deref = glsl_type_is_struct(deref->type)
|
||||||
|
? nir_build_deref_struct(b, deref, i)
|
||||||
|
: nir_build_deref_array_imm(b, deref, i);
|
||||||
|
vtn_emit_kernel_entry_point_wrapper_struct_param(b, child_deref, call,
|
||||||
|
idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static nir_function *
|
static nir_function *
|
||||||
vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
||||||
nir_function *entry_point)
|
nir_function *entry_point)
|
||||||
|
|
@ -6796,7 +6817,8 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
||||||
|
|
||||||
nir_call_instr *call = nir_call_instr_create(b->nb.shader, entry_point);
|
nir_call_instr *call = nir_call_instr_create(b->nb.shader, entry_point);
|
||||||
|
|
||||||
for (unsigned i = 0; i < entry_point->num_params; ++i) {
|
unsigned call_idx = 0;
|
||||||
|
for (unsigned i = 0; i < b->entry_point->func->type->length; ++i) {
|
||||||
struct vtn_type *param_type = b->entry_point->func->type->params[i];
|
struct vtn_type *param_type = b->entry_point->func->type->params[i];
|
||||||
|
|
||||||
b->shader->info.cs.has_variable_shared_mem |=
|
b->shader->info.cs.has_variable_shared_mem |=
|
||||||
|
|
@ -6837,17 +6859,30 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
||||||
nir_variable *copy_var =
|
nir_variable *copy_var =
|
||||||
nir_local_variable_create(impl, in_var->type, "copy_in");
|
nir_local_variable_create(impl, in_var->type, "copy_in");
|
||||||
nir_copy_var(&b->nb, copy_var, in_var);
|
nir_copy_var(&b->nb, copy_var, in_var);
|
||||||
call->params[i] =
|
call->params[call_idx++] =
|
||||||
nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->def);
|
nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->def);
|
||||||
} else if (param_type->base_type == vtn_base_type_image ||
|
} else if (param_type->base_type == vtn_base_type_image ||
|
||||||
param_type->base_type == vtn_base_type_sampler) {
|
param_type->base_type == vtn_base_type_sampler) {
|
||||||
/* Don't load the var, just pass a deref of it */
|
/* Don't load the var, just pass a deref of it */
|
||||||
call->params[i] = nir_src_for_ssa(&nir_build_deref_var(&b->nb, in_var)->def);
|
call->params[call_idx++] =
|
||||||
|
nir_src_for_ssa(&nir_build_deref_var(&b->nb, in_var)->def);
|
||||||
|
} else if (param_type->base_type == vtn_base_type_struct) {
|
||||||
|
/* We decompose struct and array parameters in vtn, so we'll need to
|
||||||
|
* handle it here explicitly.
|
||||||
|
* We have to keep the arguments on the actual entry point intact,
|
||||||
|
* because the runtimes rely on it to match the SPIR-V.
|
||||||
|
*/
|
||||||
|
nir_deref_instr *deref = nir_build_deref_var(&b->nb, in_var);
|
||||||
|
vtn_emit_kernel_entry_point_wrapper_struct_param(&b->nb, deref, call,
|
||||||
|
&call_idx);
|
||||||
} else {
|
} else {
|
||||||
call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var));
|
call->params[call_idx++] =
|
||||||
|
nir_src_for_ssa(nir_load_var(&b->nb, in_var));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(call_idx == entry_point->num_params);
|
||||||
|
|
||||||
nir_builder_instr_insert(&b->nb, &call->instr);
|
nir_builder_instr_insert(&b->nb, &call->instr);
|
||||||
|
|
||||||
return main_entry_point;
|
return main_entry_point;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue