From 4b2c78c08a61521be77d6bdaf34d9fadaae3f600 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 23 Oct 2020 14:22:23 -0500 Subject: [PATCH] spirv: Implement the function portion of the Linkage capability Acked-by: Lionel Landwerlin Part-of: --- src/compiler/shader_info.h | 1 + src/compiler/spirv/spirv_to_nir.c | 5 ++++- src/compiler/spirv/vtn_cfg.c | 35 +++++++++++++++++++++++++++++++ src/compiler/spirv/vtn_opencl.c | 3 +-- src/compiler/spirv/vtn_private.h | 6 ++++++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h index b651ab15d22..e759d542262 100644 --- a/src/compiler/shader_info.h +++ b/src/compiler/shader_info.h @@ -72,6 +72,7 @@ struct spirv_supported_capabilities { bool kernel; bool kernel_image; bool kernel_image_read_write; + bool linkage; bool literal_sampler; bool mesh_shading_nv; bool min_lod; diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index cd1c50be699..974b23cbc19 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -433,7 +433,7 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id) return si; } -static const char * +const char * vtn_string_literal(struct vtn_builder *b, const uint32_t *words, unsigned word_count, unsigned *words_used) { @@ -681,6 +681,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode, unreachable("Invalid decoration opcode"); } dec->decoration = *(w++); + dec->num_operands = w_end - w; dec->operands = w; /* Link into the list */ @@ -4482,6 +4483,8 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode, if (!b->options->create_library) vtn_warn("Unsupported SPIR-V capability: %s", spirv_capability_to_string(cap)); + spv_check_supported(linkage, cap); + vtn_warn("The SPIR-V Linkage capability is not fully supported"); break; case SpvCapabilitySparseResidency: diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 2bf698629c1..d408e2437ed 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -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 vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode, 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.parent = NULL; list_inithead(&b->func->body); + b->func->linkage = SpvLinkageTypeMax; b->func->control = w[3]; 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); val->func = b->func; + vtn_foreach_decoration(b, val, function_decoration_cb, b->func); + b->func->type = vtn_get_type(b, w[4]); 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: b->func->end = w; 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 * just a prototype so delete the function_impl. */ 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; break; diff --git a/src/compiler/spirv/vtn_opencl.c b/src/compiler/spirv/vtn_opencl.c index 0b8d2278cca..befb6eaf3b3 100644 --- a/src/compiler/spirv/vtn_opencl.c +++ b/src/compiler/spirv/vtn_opencl.c @@ -812,8 +812,7 @@ handle_printf(struct vtn_builder *b, uint32_t opcode, glsl_struct_type(fields, num_srcs - 1, "printf", true); /* Step 3, create a variable of that type and populate its fields */ - nir_variable *var = nir_local_variable_create(b->func->nir_func->impl, - struct_type, NULL); + nir_variable *var = nir_local_variable_create(b->nb.impl, struct_type, NULL); nir_deref_instr *deref_var = nir_build_deref_var(&b->nb, var); size_t fmt_pos = 0; for (unsigned i = 1; i < num_srcs; ++i) { diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 631d16d9b63..a1a157b6972 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -274,6 +274,7 @@ struct vtn_function { const uint32_t *end; + SpvLinkageType linkage; SpvFunctionControlMask control; }; @@ -646,6 +647,7 @@ struct vtn_decoration { */ int scope; + uint32_t num_operands; const uint32_t *operands; struct vtn_value *group; @@ -743,6 +745,10 @@ struct vtn_builder { 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 * vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr); struct vtn_pointer *