spirv: Implement the function portion of the Linkage capability

Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15486>
This commit is contained in:
Jason Ekstrand
2020-10-23 14:22:23 -05:00
committed by Marge Bot
parent 80a076382d
commit 4b2c78c08a
5 changed files with 47 additions and 3 deletions

View File

@@ -72,6 +72,7 @@ struct spirv_supported_capabilities {
bool kernel; bool kernel;
bool kernel_image; bool kernel_image;
bool kernel_image_read_write; bool kernel_image_read_write;
bool linkage;
bool literal_sampler; bool literal_sampler;
bool mesh_shading_nv; bool mesh_shading_nv;
bool min_lod; bool min_lod;

View File

@@ -433,7 +433,7 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)
return si; return si;
} }
static const char * const char *
vtn_string_literal(struct vtn_builder *b, const uint32_t *words, vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
unsigned word_count, unsigned *words_used) unsigned word_count, unsigned *words_used)
{ {
@@ -681,6 +681,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
unreachable("Invalid decoration opcode"); unreachable("Invalid decoration opcode");
} }
dec->decoration = *(w++); dec->decoration = *(w++);
dec->num_operands = w_end - w;
dec->operands = w; dec->operands = w;
/* Link into the list */ /* Link into the list */
@@ -4482,6 +4483,8 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
if (!b->options->create_library) if (!b->options->create_library)
vtn_warn("Unsupported SPIR-V capability: %s", vtn_warn("Unsupported SPIR-V capability: %s",
spirv_capability_to_string(cap)); spirv_capability_to_string(cap));
spv_check_supported(linkage, cap);
vtn_warn("The SPIR-V Linkage capability is not fully supported");
break; break;
case SpvCapabilitySparseResidency: case SpvCapabilitySparseResidency:

View File

@@ -148,6 +148,29 @@ vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
} }
} }
static void
function_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
const struct vtn_decoration *dec, void *void_func)
{
struct vtn_function *func = void_func;
switch (dec->decoration) {
case SpvDecorationLinkageAttributes: {
unsigned name_words;
const char *name =
vtn_string_literal(b, dec->operands, dec->num_operands, &name_words);
vtn_fail_if(name_words >= dec->num_operands,
"Malformed LinkageAttributes decoration");
(void)name; /* TODO: What is this? */
func->linkage = dec->operands[name_words];
break;
}
default:
break;
}
}
static bool static bool
vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode, vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count) const uint32_t *w, unsigned count)
@@ -160,12 +183,15 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
b->func->node.type = vtn_cf_node_type_function; b->func->node.type = vtn_cf_node_type_function;
b->func->node.parent = NULL; b->func->node.parent = NULL;
list_inithead(&b->func->body); list_inithead(&b->func->body);
b->func->linkage = SpvLinkageTypeMax;
b->func->control = w[3]; b->func->control = w[3];
UNUSED const struct glsl_type *result_type = vtn_get_type(b, w[1])->type; UNUSED const struct glsl_type *result_type = vtn_get_type(b, w[1])->type;
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function); struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function);
val->func = b->func; val->func = b->func;
vtn_foreach_decoration(b, val, function_decoration_cb, b->func);
b->func->type = vtn_get_type(b, w[4]); b->func->type = vtn_get_type(b, w[4]);
const struct vtn_type *func_type = b->func->type; const struct vtn_type *func_type = b->func->type;
@@ -221,10 +247,19 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpFunctionEnd: case SpvOpFunctionEnd:
b->func->end = w; b->func->end = w;
if (b->func->start_block == NULL) { if (b->func->start_block == NULL) {
vtn_fail_if(b->func->linkage != SpvLinkageTypeImport,
"A function declaration (an OpFunction with no basic "
"blocks), must have a Linkage Attributes Decoration "
"with the Import Linkage Type.");
/* In this case, the function didn't have any actual blocks. It's /* In this case, the function didn't have any actual blocks. It's
* just a prototype so delete the function_impl. * just a prototype so delete the function_impl.
*/ */
b->func->nir_func->impl = NULL; b->func->nir_func->impl = NULL;
} else {
vtn_fail_if(b->func->linkage == SpvLinkageTypeImport,
"A function definition (an OpFunction with basic blocks) "
"cannot be decorated with the Import Linkage Type.");
} }
b->func = NULL; b->func = NULL;
break; break;

View File

@@ -812,8 +812,7 @@ handle_printf(struct vtn_builder *b, uint32_t opcode,
glsl_struct_type(fields, num_srcs - 1, "printf", true); glsl_struct_type(fields, num_srcs - 1, "printf", true);
/* Step 3, create a variable of that type and populate its fields */ /* Step 3, create a variable of that type and populate its fields */
nir_variable *var = nir_local_variable_create(b->func->nir_func->impl, nir_variable *var = nir_local_variable_create(b->nb.impl, struct_type, NULL);
struct_type, NULL);
nir_deref_instr *deref_var = nir_build_deref_var(&b->nb, var); nir_deref_instr *deref_var = nir_build_deref_var(&b->nb, var);
size_t fmt_pos = 0; size_t fmt_pos = 0;
for (unsigned i = 1; i < num_srcs; ++i) { for (unsigned i = 1; i < num_srcs; ++i) {

View File

@@ -274,6 +274,7 @@ struct vtn_function {
const uint32_t *end; const uint32_t *end;
SpvLinkageType linkage;
SpvFunctionControlMask control; SpvFunctionControlMask control;
}; };
@@ -646,6 +647,7 @@ struct vtn_decoration {
*/ */
int scope; int scope;
uint32_t num_operands;
const uint32_t *operands; const uint32_t *operands;
struct vtn_value *group; struct vtn_value *group;
@@ -743,6 +745,10 @@ struct vtn_builder {
unsigned mem_model; unsigned mem_model;
}; };
const char *
vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
unsigned word_count, unsigned *words_used);
nir_ssa_def * nir_ssa_def *
vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr); vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr);
struct vtn_pointer * struct vtn_pointer *