Path: blob/21.2-virgl/src/compiler/spirv/spirv_to_nir.c
4545 views
/*1* Copyright © 2015 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* Authors:23* Jason Ekstrand ([email protected])24*25*/2627#include "vtn_private.h"28#include "nir/nir_vla.h"29#include "nir/nir_control_flow.h"30#include "nir/nir_constant_expressions.h"31#include "nir/nir_deref.h"32#include "spirv_info.h"3334#include "util/format/u_format.h"35#include "util/u_math.h"36#include "util/u_string.h"3738#include <stdio.h>3940#ifndef NDEBUG41static enum nir_spirv_debug_level42vtn_default_log_level(void)43{44enum nir_spirv_debug_level level = NIR_SPIRV_DEBUG_LEVEL_WARNING;45const char *vtn_log_level_strings[] = {46[NIR_SPIRV_DEBUG_LEVEL_WARNING] = "warning",47[NIR_SPIRV_DEBUG_LEVEL_INFO] = "info",48[NIR_SPIRV_DEBUG_LEVEL_ERROR] = "error",49};50const char *str = getenv("MESA_SPIRV_LOG_LEVEL");5152if (str == NULL)53return NIR_SPIRV_DEBUG_LEVEL_WARNING;5455for (int i = 0; i < ARRAY_SIZE(vtn_log_level_strings); i++) {56if (strcasecmp(str, vtn_log_level_strings[i]) == 0) {57level = i;58break;59}60}6162return level;63}64#endif6566void67vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,68size_t spirv_offset, const char *message)69{70if (b->options->debug.func) {71b->options->debug.func(b->options->debug.private_data,72level, spirv_offset, message);73}7475#ifndef NDEBUG76static enum nir_spirv_debug_level default_level =77NIR_SPIRV_DEBUG_LEVEL_INVALID;7879if (default_level == NIR_SPIRV_DEBUG_LEVEL_INVALID)80default_level = vtn_default_log_level();8182if (level >= default_level)83fprintf(stderr, "%s\n", message);84#endif85}8687void88vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level,89size_t spirv_offset, const char *fmt, ...)90{91va_list args;92char *msg;9394va_start(args, fmt);95msg = ralloc_vasprintf(NULL, fmt, args);96va_end(args);9798vtn_log(b, level, spirv_offset, msg);99100ralloc_free(msg);101}102103static void104vtn_log_err(struct vtn_builder *b,105enum nir_spirv_debug_level level, const char *prefix,106const char *file, unsigned line,107const char *fmt, va_list args)108{109char *msg;110111msg = ralloc_strdup(NULL, prefix);112113#ifndef NDEBUG114ralloc_asprintf_append(&msg, " In file %s:%u\n", file, line);115#endif116117ralloc_asprintf_append(&msg, " ");118119ralloc_vasprintf_append(&msg, fmt, args);120121ralloc_asprintf_append(&msg, "\n %zu bytes into the SPIR-V binary",122b->spirv_offset);123124if (b->file) {125ralloc_asprintf_append(&msg,126"\n in SPIR-V source file %s, line %d, col %d",127b->file, b->line, b->col);128}129130vtn_log(b, level, b->spirv_offset, msg);131132ralloc_free(msg);133}134135static void136vtn_dump_shader(struct vtn_builder *b, const char *path, const char *prefix)137{138static int idx = 0;139140char filename[1024];141int len = snprintf(filename, sizeof(filename), "%s/%s-%d.spirv",142path, prefix, idx++);143if (len < 0 || len >= sizeof(filename))144return;145146FILE *f = fopen(filename, "w");147if (f == NULL)148return;149150fwrite(b->spirv, sizeof(*b->spirv), b->spirv_word_count, f);151fclose(f);152153vtn_info("SPIR-V shader dumped to %s", filename);154}155156void157_vtn_warn(struct vtn_builder *b, const char *file, unsigned line,158const char *fmt, ...)159{160va_list args;161162va_start(args, fmt);163vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_WARNING, "SPIR-V WARNING:\n",164file, line, fmt, args);165va_end(args);166}167168void169_vtn_err(struct vtn_builder *b, const char *file, unsigned line,170const char *fmt, ...)171{172va_list args;173174va_start(args, fmt);175vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_ERROR, "SPIR-V ERROR:\n",176file, line, fmt, args);177va_end(args);178}179180void181_vtn_fail(struct vtn_builder *b, const char *file, unsigned line,182const char *fmt, ...)183{184va_list args;185186va_start(args, fmt);187vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_ERROR, "SPIR-V parsing FAILED:\n",188file, line, fmt, args);189va_end(args);190191const char *dump_path = getenv("MESA_SPIRV_FAIL_DUMP_PATH");192if (dump_path)193vtn_dump_shader(b, dump_path, "fail");194195vtn_longjmp(b->fail_jump, 1);196}197198static struct vtn_ssa_value *199vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type)200{201struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);202val->type = glsl_get_bare_type(type);203204if (glsl_type_is_vector_or_scalar(type)) {205unsigned num_components = glsl_get_vector_elements(val->type);206unsigned bit_size = glsl_get_bit_size(val->type);207val->def = nir_ssa_undef(&b->nb, num_components, bit_size);208} else {209unsigned elems = glsl_get_length(val->type);210val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);211if (glsl_type_is_array_or_matrix(type)) {212const struct glsl_type *elem_type = glsl_get_array_element(type);213for (unsigned i = 0; i < elems; i++)214val->elems[i] = vtn_undef_ssa_value(b, elem_type);215} else {216vtn_assert(glsl_type_is_struct_or_ifc(type));217for (unsigned i = 0; i < elems; i++) {218const struct glsl_type *elem_type = glsl_get_struct_field(type, i);219val->elems[i] = vtn_undef_ssa_value(b, elem_type);220}221}222}223224return val;225}226227static struct vtn_ssa_value *228vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant,229const struct glsl_type *type)230{231struct hash_entry *entry = _mesa_hash_table_search(b->const_table, constant);232233if (entry)234return entry->data;235236struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);237val->type = glsl_get_bare_type(type);238239if (glsl_type_is_vector_or_scalar(type)) {240unsigned num_components = glsl_get_vector_elements(val->type);241unsigned bit_size = glsl_get_bit_size(type);242nir_load_const_instr *load =243nir_load_const_instr_create(b->shader, num_components, bit_size);244245memcpy(load->value, constant->values,246sizeof(nir_const_value) * num_components);247248nir_instr_insert_before_cf_list(&b->nb.impl->body, &load->instr);249val->def = &load->def;250} else {251unsigned elems = glsl_get_length(val->type);252val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);253if (glsl_type_is_array_or_matrix(type)) {254const struct glsl_type *elem_type = glsl_get_array_element(type);255for (unsigned i = 0; i < elems; i++) {256val->elems[i] = vtn_const_ssa_value(b, constant->elements[i],257elem_type);258}259} else {260vtn_assert(glsl_type_is_struct_or_ifc(type));261for (unsigned i = 0; i < elems; i++) {262const struct glsl_type *elem_type = glsl_get_struct_field(type, i);263val->elems[i] = vtn_const_ssa_value(b, constant->elements[i],264elem_type);265}266}267}268269return val;270}271272struct vtn_ssa_value *273vtn_ssa_value(struct vtn_builder *b, uint32_t value_id)274{275struct vtn_value *val = vtn_untyped_value(b, value_id);276switch (val->value_type) {277case vtn_value_type_undef:278return vtn_undef_ssa_value(b, val->type->type);279280case vtn_value_type_constant:281return vtn_const_ssa_value(b, val->constant, val->type->type);282283case vtn_value_type_ssa:284return val->ssa;285286case vtn_value_type_pointer:287vtn_assert(val->pointer->ptr_type && val->pointer->ptr_type->type);288struct vtn_ssa_value *ssa =289vtn_create_ssa_value(b, val->pointer->ptr_type->type);290ssa->def = vtn_pointer_to_ssa(b, val->pointer);291return ssa;292293default:294vtn_fail("Invalid type for an SSA value");295}296}297298struct vtn_value *299vtn_push_ssa_value(struct vtn_builder *b, uint32_t value_id,300struct vtn_ssa_value *ssa)301{302struct vtn_type *type = vtn_get_value_type(b, value_id);303304/* See vtn_create_ssa_value */305vtn_fail_if(ssa->type != glsl_get_bare_type(type->type),306"Type mismatch for SPIR-V SSA value");307308struct vtn_value *val;309if (type->base_type == vtn_base_type_pointer) {310val = vtn_push_pointer(b, value_id, vtn_pointer_from_ssa(b, ssa->def, type));311} else {312/* Don't trip the value_type_ssa check in vtn_push_value */313val = vtn_push_value(b, value_id, vtn_value_type_invalid);314val->value_type = vtn_value_type_ssa;315val->ssa = ssa;316}317318return val;319}320321nir_ssa_def *322vtn_get_nir_ssa(struct vtn_builder *b, uint32_t value_id)323{324struct vtn_ssa_value *ssa = vtn_ssa_value(b, value_id);325vtn_fail_if(!glsl_type_is_vector_or_scalar(ssa->type),326"Expected a vector or scalar type");327return ssa->def;328}329330struct vtn_value *331vtn_push_nir_ssa(struct vtn_builder *b, uint32_t value_id, nir_ssa_def *def)332{333/* Types for all SPIR-V SSA values are set as part of a pre-pass so the334* type will be valid by the time we get here.335*/336struct vtn_type *type = vtn_get_value_type(b, value_id);337vtn_fail_if(def->num_components != glsl_get_vector_elements(type->type) ||338def->bit_size != glsl_get_bit_size(type->type),339"Mismatch between NIR and SPIR-V type.");340struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, type->type);341ssa->def = def;342return vtn_push_ssa_value(b, value_id, ssa);343}344345static enum gl_access_qualifier346spirv_to_gl_access_qualifier(struct vtn_builder *b,347SpvAccessQualifier access_qualifier)348{349switch (access_qualifier) {350case SpvAccessQualifierReadOnly:351return ACCESS_NON_WRITEABLE;352case SpvAccessQualifierWriteOnly:353return ACCESS_NON_READABLE;354case SpvAccessQualifierReadWrite:355return 0;356default:357vtn_fail("Invalid image access qualifier");358}359}360361static nir_deref_instr *362vtn_get_image(struct vtn_builder *b, uint32_t value_id,363enum gl_access_qualifier *access)364{365struct vtn_type *type = vtn_get_value_type(b, value_id);366vtn_assert(type->base_type == vtn_base_type_image);367if (access)368*access |= spirv_to_gl_access_qualifier(b, type->access_qualifier);369return nir_build_deref_cast(&b->nb, vtn_get_nir_ssa(b, value_id),370nir_var_uniform, type->glsl_image, 0);371}372373static void374vtn_push_image(struct vtn_builder *b, uint32_t value_id,375nir_deref_instr *deref, bool propagate_non_uniform)376{377struct vtn_type *type = vtn_get_value_type(b, value_id);378vtn_assert(type->base_type == vtn_base_type_image);379struct vtn_value *value = vtn_push_nir_ssa(b, value_id, &deref->dest.ssa);380value->propagated_non_uniform = propagate_non_uniform;381}382383static nir_deref_instr *384vtn_get_sampler(struct vtn_builder *b, uint32_t value_id)385{386struct vtn_type *type = vtn_get_value_type(b, value_id);387vtn_assert(type->base_type == vtn_base_type_sampler);388return nir_build_deref_cast(&b->nb, vtn_get_nir_ssa(b, value_id),389nir_var_uniform, glsl_bare_sampler_type(), 0);390}391392nir_ssa_def *393vtn_sampled_image_to_nir_ssa(struct vtn_builder *b,394struct vtn_sampled_image si)395{396return nir_vec2(&b->nb, &si.image->dest.ssa, &si.sampler->dest.ssa);397}398399static void400vtn_push_sampled_image(struct vtn_builder *b, uint32_t value_id,401struct vtn_sampled_image si, bool propagate_non_uniform)402{403struct vtn_type *type = vtn_get_value_type(b, value_id);404vtn_assert(type->base_type == vtn_base_type_sampled_image);405struct vtn_value *value = vtn_push_nir_ssa(b, value_id,406vtn_sampled_image_to_nir_ssa(b, si));407value->propagated_non_uniform = propagate_non_uniform;408}409410static struct vtn_sampled_image411vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)412{413struct vtn_type *type = vtn_get_value_type(b, value_id);414vtn_assert(type->base_type == vtn_base_type_sampled_image);415nir_ssa_def *si_vec2 = vtn_get_nir_ssa(b, value_id);416417struct vtn_sampled_image si = { NULL, };418si.image = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 0),419nir_var_uniform,420type->image->glsl_image, 0);421si.sampler = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 1),422nir_var_uniform,423glsl_bare_sampler_type(), 0);424return si;425}426427static const char *428vtn_string_literal(struct vtn_builder *b, const uint32_t *words,429unsigned word_count, unsigned *words_used)430{431/* From the SPIR-V spec:432*433* "A string is interpreted as a nul-terminated stream of characters.434* The character set is Unicode in the UTF-8 encoding scheme. The UTF-8435* octets (8-bit bytes) are packed four per word, following the436* little-endian convention (i.e., the first octet is in the437* lowest-order 8 bits of the word). The final word contains the438* string’s nul-termination character (0), and all contents past the439* end of the string in the final word are padded with 0."440*441* On big-endian, we need to byte-swap.442*/443#if UTIL_ARCH_BIG_ENDIAN444{445uint32_t *copy = ralloc_array(b, uint32_t, word_count);446for (unsigned i = 0; i < word_count; i++)447copy[i] = util_bswap32(words[i]);448words = copy;449}450#endif451452const char *str = (char *)words;453const char *end = memchr(str, 0, word_count * 4);454vtn_fail_if(end == NULL, "String is not null-terminated");455456if (words_used)457*words_used = DIV_ROUND_UP(end - str + 1, sizeof(*words));458459return str;460}461462const uint32_t *463vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,464const uint32_t *end, vtn_instruction_handler handler)465{466b->file = NULL;467b->line = -1;468b->col = -1;469470const uint32_t *w = start;471while (w < end) {472SpvOp opcode = w[0] & SpvOpCodeMask;473unsigned count = w[0] >> SpvWordCountShift;474vtn_assert(count >= 1 && w + count <= end);475476b->spirv_offset = (uint8_t *)w - (uint8_t *)b->spirv;477478switch (opcode) {479case SpvOpNop:480break; /* Do nothing */481482case SpvOpLine:483b->file = vtn_value(b, w[1], vtn_value_type_string)->str;484b->line = w[2];485b->col = w[3];486break;487488case SpvOpNoLine:489b->file = NULL;490b->line = -1;491b->col = -1;492break;493494default:495if (!handler(b, opcode, w, count))496return w;497break;498}499500w += count;501}502503b->spirv_offset = 0;504b->file = NULL;505b->line = -1;506b->col = -1;507508assert(w == end);509return w;510}511512static bool513vtn_handle_non_semantic_instruction(struct vtn_builder *b, SpvOp ext_opcode,514const uint32_t *w, unsigned count)515{516/* Do nothing. */517return true;518}519520static void521vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,522const uint32_t *w, unsigned count)523{524switch (opcode) {525case SpvOpExtInstImport: {526struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_extension);527const char *ext = vtn_string_literal(b, &w[2], count - 2, NULL);528if (strcmp(ext, "GLSL.std.450") == 0) {529val->ext_handler = vtn_handle_glsl450_instruction;530} else if ((strcmp(ext, "SPV_AMD_gcn_shader") == 0)531&& (b->options && b->options->caps.amd_gcn_shader)) {532val->ext_handler = vtn_handle_amd_gcn_shader_instruction;533} else if ((strcmp(ext, "SPV_AMD_shader_ballot") == 0)534&& (b->options && b->options->caps.amd_shader_ballot)) {535val->ext_handler = vtn_handle_amd_shader_ballot_instruction;536} else if ((strcmp(ext, "SPV_AMD_shader_trinary_minmax") == 0)537&& (b->options && b->options->caps.amd_trinary_minmax)) {538val->ext_handler = vtn_handle_amd_shader_trinary_minmax_instruction;539} else if ((strcmp(ext, "SPV_AMD_shader_explicit_vertex_parameter") == 0)540&& (b->options && b->options->caps.amd_shader_explicit_vertex_parameter)) {541val->ext_handler = vtn_handle_amd_shader_explicit_vertex_parameter_instruction;542} else if (strcmp(ext, "OpenCL.std") == 0) {543val->ext_handler = vtn_handle_opencl_instruction;544} else if (strstr(ext, "NonSemantic.") == ext) {545val->ext_handler = vtn_handle_non_semantic_instruction;546} else {547vtn_fail("Unsupported extension: %s", ext);548}549break;550}551552case SpvOpExtInst: {553struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_extension);554bool handled = val->ext_handler(b, w[4], w, count);555vtn_assert(handled);556break;557}558559default:560vtn_fail_with_opcode("Unhandled opcode", opcode);561}562}563564static void565_foreach_decoration_helper(struct vtn_builder *b,566struct vtn_value *base_value,567int parent_member,568struct vtn_value *value,569vtn_decoration_foreach_cb cb, void *data)570{571for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) {572int member;573if (dec->scope == VTN_DEC_DECORATION) {574member = parent_member;575} else if (dec->scope >= VTN_DEC_STRUCT_MEMBER0) {576vtn_fail_if(value->value_type != vtn_value_type_type ||577value->type->base_type != vtn_base_type_struct,578"OpMemberDecorate and OpGroupMemberDecorate are only "579"allowed on OpTypeStruct");580/* This means we haven't recursed yet */581assert(value == base_value);582583member = dec->scope - VTN_DEC_STRUCT_MEMBER0;584585vtn_fail_if(member >= base_value->type->length,586"OpMemberDecorate specifies member %d but the "587"OpTypeStruct has only %u members",588member, base_value->type->length);589} else {590/* Not a decoration */591assert(dec->scope == VTN_DEC_EXECUTION_MODE);592continue;593}594595if (dec->group) {596assert(dec->group->value_type == vtn_value_type_decoration_group);597_foreach_decoration_helper(b, base_value, member, dec->group,598cb, data);599} else {600cb(b, base_value, member, dec, data);601}602}603}604605/** Iterates (recursively if needed) over all of the decorations on a value606*607* This function iterates over all of the decorations applied to a given608* value. If it encounters a decoration group, it recurses into the group609* and iterates over all of those decorations as well.610*/611void612vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,613vtn_decoration_foreach_cb cb, void *data)614{615_foreach_decoration_helper(b, value, -1, value, cb, data);616}617618void619vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,620vtn_execution_mode_foreach_cb cb, void *data)621{622for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) {623if (dec->scope != VTN_DEC_EXECUTION_MODE)624continue;625626assert(dec->group == NULL);627cb(b, value, dec, data);628}629}630631void632vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,633const uint32_t *w, unsigned count)634{635const uint32_t *w_end = w + count;636const uint32_t target = w[1];637w += 2;638639switch (opcode) {640case SpvOpDecorationGroup:641vtn_push_value(b, target, vtn_value_type_decoration_group);642break;643644case SpvOpDecorate:645case SpvOpDecorateId:646case SpvOpMemberDecorate:647case SpvOpDecorateString:648case SpvOpMemberDecorateString:649case SpvOpExecutionMode:650case SpvOpExecutionModeId: {651struct vtn_value *val = vtn_untyped_value(b, target);652653struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);654switch (opcode) {655case SpvOpDecorate:656case SpvOpDecorateId:657case SpvOpDecorateString:658dec->scope = VTN_DEC_DECORATION;659break;660case SpvOpMemberDecorate:661case SpvOpMemberDecorateString:662dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++);663vtn_fail_if(dec->scope < VTN_DEC_STRUCT_MEMBER0, /* overflow */664"Member argument of OpMemberDecorate too large");665break;666case SpvOpExecutionMode:667case SpvOpExecutionModeId:668dec->scope = VTN_DEC_EXECUTION_MODE;669break;670default:671unreachable("Invalid decoration opcode");672}673dec->decoration = *(w++);674dec->operands = w;675676/* Link into the list */677dec->next = val->decoration;678val->decoration = dec;679break;680}681682case SpvOpGroupMemberDecorate:683case SpvOpGroupDecorate: {684struct vtn_value *group =685vtn_value(b, target, vtn_value_type_decoration_group);686687for (; w < w_end; w++) {688struct vtn_value *val = vtn_untyped_value(b, *w);689struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);690691dec->group = group;692if (opcode == SpvOpGroupDecorate) {693dec->scope = VTN_DEC_DECORATION;694} else {695dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(++w);696vtn_fail_if(dec->scope < 0, /* Check for overflow */697"Member argument of OpGroupMemberDecorate too large");698}699700/* Link into the list */701dec->next = val->decoration;702val->decoration = dec;703}704break;705}706707default:708unreachable("Unhandled opcode");709}710}711712struct member_decoration_ctx {713unsigned num_fields;714struct glsl_struct_field *fields;715struct vtn_type *type;716};717718/**719* Returns true if the given type contains a struct decorated Block or720* BufferBlock721*/722bool723vtn_type_contains_block(struct vtn_builder *b, struct vtn_type *type)724{725switch (type->base_type) {726case vtn_base_type_array:727return vtn_type_contains_block(b, type->array_element);728case vtn_base_type_struct:729if (type->block || type->buffer_block)730return true;731for (unsigned i = 0; i < type->length; i++) {732if (vtn_type_contains_block(b, type->members[i]))733return true;734}735return false;736default:737return false;738}739}740741/** Returns true if two types are "compatible", i.e. you can do an OpLoad,742* OpStore, or OpCopyMemory between them without breaking anything.743* Technically, the SPIR-V rules require the exact same type ID but this lets744* us internally be a bit looser.745*/746bool747vtn_types_compatible(struct vtn_builder *b,748struct vtn_type *t1, struct vtn_type *t2)749{750if (t1->id == t2->id)751return true;752753if (t1->base_type != t2->base_type)754return false;755756switch (t1->base_type) {757case vtn_base_type_void:758case vtn_base_type_scalar:759case vtn_base_type_vector:760case vtn_base_type_matrix:761case vtn_base_type_image:762case vtn_base_type_sampler:763case vtn_base_type_sampled_image:764case vtn_base_type_event:765return t1->type == t2->type;766767case vtn_base_type_array:768return t1->length == t2->length &&769vtn_types_compatible(b, t1->array_element, t2->array_element);770771case vtn_base_type_pointer:772return vtn_types_compatible(b, t1->deref, t2->deref);773774case vtn_base_type_struct:775if (t1->length != t2->length)776return false;777778for (unsigned i = 0; i < t1->length; i++) {779if (!vtn_types_compatible(b, t1->members[i], t2->members[i]))780return false;781}782return true;783784case vtn_base_type_accel_struct:785return true;786787case vtn_base_type_function:788/* This case shouldn't get hit since you can't copy around function789* types. Just require them to be identical.790*/791return false;792}793794vtn_fail("Invalid base type");795}796797struct vtn_type *798vtn_type_without_array(struct vtn_type *type)799{800while (type->base_type == vtn_base_type_array)801type = type->array_element;802return type;803}804805/* does a shallow copy of a vtn_type */806807static struct vtn_type *808vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)809{810struct vtn_type *dest = ralloc(b, struct vtn_type);811*dest = *src;812813switch (src->base_type) {814case vtn_base_type_void:815case vtn_base_type_scalar:816case vtn_base_type_vector:817case vtn_base_type_matrix:818case vtn_base_type_array:819case vtn_base_type_pointer:820case vtn_base_type_image:821case vtn_base_type_sampler:822case vtn_base_type_sampled_image:823case vtn_base_type_event:824case vtn_base_type_accel_struct:825/* Nothing more to do */826break;827828case vtn_base_type_struct:829dest->members = ralloc_array(b, struct vtn_type *, src->length);830memcpy(dest->members, src->members,831src->length * sizeof(src->members[0]));832833dest->offsets = ralloc_array(b, unsigned, src->length);834memcpy(dest->offsets, src->offsets,835src->length * sizeof(src->offsets[0]));836break;837838case vtn_base_type_function:839dest->params = ralloc_array(b, struct vtn_type *, src->length);840memcpy(dest->params, src->params, src->length * sizeof(src->params[0]));841break;842}843844return dest;845}846847static const struct glsl_type *848wrap_type_in_array(const struct glsl_type *type,849const struct glsl_type *array_type)850{851if (!glsl_type_is_array(array_type))852return type;853854const struct glsl_type *elem_type =855wrap_type_in_array(type, glsl_get_array_element(array_type));856return glsl_array_type(elem_type, glsl_get_length(array_type),857glsl_get_explicit_stride(array_type));858}859860static bool861vtn_type_needs_explicit_layout(struct vtn_builder *b, struct vtn_type *type,862enum vtn_variable_mode mode)863{864/* For OpenCL we never want to strip the info from the types, and it makes865* type comparisons easier in later stages.866*/867if (b->options->environment == NIR_SPIRV_OPENCL)868return true;869870switch (mode) {871case vtn_variable_mode_input:872case vtn_variable_mode_output:873/* Layout decorations kept because we need offsets for XFB arrays of874* blocks.875*/876return b->shader->info.has_transform_feedback_varyings;877878case vtn_variable_mode_ssbo:879case vtn_variable_mode_phys_ssbo:880case vtn_variable_mode_ubo:881case vtn_variable_mode_push_constant:882case vtn_variable_mode_shader_record:883return true;884885case vtn_variable_mode_workgroup:886return b->options->caps.workgroup_memory_explicit_layout;887888default:889return false;890}891}892893const struct glsl_type *894vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,895enum vtn_variable_mode mode)896{897if (mode == vtn_variable_mode_atomic_counter) {898vtn_fail_if(glsl_without_array(type->type) != glsl_uint_type(),899"Variables in the AtomicCounter storage class should be "900"(possibly arrays of arrays of) uint.");901return wrap_type_in_array(glsl_atomic_uint_type(), type->type);902}903904if (mode == vtn_variable_mode_uniform) {905switch (type->base_type) {906case vtn_base_type_array: {907const struct glsl_type *elem_type =908vtn_type_get_nir_type(b, type->array_element, mode);909910return glsl_array_type(elem_type, type->length,911glsl_get_explicit_stride(type->type));912}913914case vtn_base_type_struct: {915bool need_new_struct = false;916const uint32_t num_fields = type->length;917NIR_VLA(struct glsl_struct_field, fields, num_fields);918for (unsigned i = 0; i < num_fields; i++) {919fields[i] = *glsl_get_struct_field_data(type->type, i);920const struct glsl_type *field_nir_type =921vtn_type_get_nir_type(b, type->members[i], mode);922if (fields[i].type != field_nir_type) {923fields[i].type = field_nir_type;924need_new_struct = true;925}926}927if (need_new_struct) {928if (glsl_type_is_interface(type->type)) {929return glsl_interface_type(fields, num_fields,930/* packing */ 0, false,931glsl_get_type_name(type->type));932} else {933return glsl_struct_type(fields, num_fields,934glsl_get_type_name(type->type),935glsl_struct_type_is_packed(type->type));936}937} else {938/* No changes, just pass it on */939return type->type;940}941}942943case vtn_base_type_image:944return type->glsl_image;945946case vtn_base_type_sampler:947return glsl_bare_sampler_type();948949case vtn_base_type_sampled_image:950return type->image->glsl_image;951952default:953return type->type;954}955}956957/* Layout decorations are allowed but ignored in certain conditions,958* to allow SPIR-V generators perform type deduplication. Discard959* unnecessary ones when passing to NIR.960*/961if (!vtn_type_needs_explicit_layout(b, type, mode))962return glsl_get_bare_type(type->type);963964return type->type;965}966967static struct vtn_type *968mutable_matrix_member(struct vtn_builder *b, struct vtn_type *type, int member)969{970type->members[member] = vtn_type_copy(b, type->members[member]);971type = type->members[member];972973/* We may have an array of matrices.... Oh, joy! */974while (glsl_type_is_array(type->type)) {975type->array_element = vtn_type_copy(b, type->array_element);976type = type->array_element;977}978979vtn_assert(glsl_type_is_matrix(type->type));980981return type;982}983984static void985vtn_handle_access_qualifier(struct vtn_builder *b, struct vtn_type *type,986int member, enum gl_access_qualifier access)987{988type->members[member] = vtn_type_copy(b, type->members[member]);989type = type->members[member];990991type->access |= access;992}993994static void995array_stride_decoration_cb(struct vtn_builder *b,996struct vtn_value *val, int member,997const struct vtn_decoration *dec, void *void_ctx)998{999struct vtn_type *type = val->type;10001001if (dec->decoration == SpvDecorationArrayStride) {1002if (vtn_type_contains_block(b, type)) {1003vtn_warn("The ArrayStride decoration cannot be applied to an array "1004"type which contains a structure type decorated Block "1005"or BufferBlock");1006/* Ignore the decoration */1007} else {1008vtn_fail_if(dec->operands[0] == 0, "ArrayStride must be non-zero");1009type->stride = dec->operands[0];1010}1011}1012}10131014static void1015struct_member_decoration_cb(struct vtn_builder *b,1016UNUSED struct vtn_value *val, int member,1017const struct vtn_decoration *dec, void *void_ctx)1018{1019struct member_decoration_ctx *ctx = void_ctx;10201021if (member < 0)1022return;10231024assert(member < ctx->num_fields);10251026switch (dec->decoration) {1027case SpvDecorationRelaxedPrecision:1028case SpvDecorationUniform:1029case SpvDecorationUniformId:1030break; /* FIXME: Do nothing with this for now. */1031case SpvDecorationNonWritable:1032vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_WRITEABLE);1033break;1034case SpvDecorationNonReadable:1035vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_READABLE);1036break;1037case SpvDecorationVolatile:1038vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_VOLATILE);1039break;1040case SpvDecorationCoherent:1041vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_COHERENT);1042break;1043case SpvDecorationNoPerspective:1044ctx->fields[member].interpolation = INTERP_MODE_NOPERSPECTIVE;1045break;1046case SpvDecorationFlat:1047ctx->fields[member].interpolation = INTERP_MODE_FLAT;1048break;1049case SpvDecorationExplicitInterpAMD:1050ctx->fields[member].interpolation = INTERP_MODE_EXPLICIT;1051break;1052case SpvDecorationCentroid:1053ctx->fields[member].centroid = true;1054break;1055case SpvDecorationSample:1056ctx->fields[member].sample = true;1057break;1058case SpvDecorationStream:1059/* This is handled later by var_decoration_cb in vtn_variables.c */1060break;1061case SpvDecorationLocation:1062ctx->fields[member].location = dec->operands[0];1063break;1064case SpvDecorationComponent:1065break; /* FIXME: What should we do with these? */1066case SpvDecorationBuiltIn:1067ctx->type->members[member] = vtn_type_copy(b, ctx->type->members[member]);1068ctx->type->members[member]->is_builtin = true;1069ctx->type->members[member]->builtin = dec->operands[0];1070ctx->type->builtin_block = true;1071break;1072case SpvDecorationOffset:1073ctx->type->offsets[member] = dec->operands[0];1074ctx->fields[member].offset = dec->operands[0];1075break;1076case SpvDecorationMatrixStride:1077/* Handled as a second pass */1078break;1079case SpvDecorationColMajor:1080break; /* Nothing to do here. Column-major is the default. */1081case SpvDecorationRowMajor:1082mutable_matrix_member(b, ctx->type, member)->row_major = true;1083break;10841085case SpvDecorationPatch:1086break;10871088case SpvDecorationSpecId:1089case SpvDecorationBlock:1090case SpvDecorationBufferBlock:1091case SpvDecorationArrayStride:1092case SpvDecorationGLSLShared:1093case SpvDecorationGLSLPacked:1094case SpvDecorationInvariant:1095case SpvDecorationRestrict:1096case SpvDecorationAliased:1097case SpvDecorationConstant:1098case SpvDecorationIndex:1099case SpvDecorationBinding:1100case SpvDecorationDescriptorSet:1101case SpvDecorationLinkageAttributes:1102case SpvDecorationNoContraction:1103case SpvDecorationInputAttachmentIndex:1104case SpvDecorationCPacked:1105vtn_warn("Decoration not allowed on struct members: %s",1106spirv_decoration_to_string(dec->decoration));1107break;11081109case SpvDecorationXfbBuffer:1110case SpvDecorationXfbStride:1111/* This is handled later by var_decoration_cb in vtn_variables.c */1112break;11131114case SpvDecorationSaturatedConversion:1115case SpvDecorationFuncParamAttr:1116case SpvDecorationFPRoundingMode:1117case SpvDecorationFPFastMathMode:1118case SpvDecorationAlignment:1119if (b->shader->info.stage != MESA_SHADER_KERNEL) {1120vtn_warn("Decoration only allowed for CL-style kernels: %s",1121spirv_decoration_to_string(dec->decoration));1122}1123break;11241125case SpvDecorationUserSemantic:1126case SpvDecorationUserTypeGOOGLE:1127/* User semantic decorations can safely be ignored by the driver. */1128break;11291130default:1131vtn_fail_with_decoration("Unhandled decoration", dec->decoration);1132}1133}11341135/** Chases the array type all the way down to the tail and rewrites the1136* glsl_types to be based off the tail's glsl_type.1137*/1138static void1139vtn_array_type_rewrite_glsl_type(struct vtn_type *type)1140{1141if (type->base_type != vtn_base_type_array)1142return;11431144vtn_array_type_rewrite_glsl_type(type->array_element);11451146type->type = glsl_array_type(type->array_element->type,1147type->length, type->stride);1148}11491150/* Matrix strides are handled as a separate pass because we need to know1151* whether the matrix is row-major or not first.1152*/1153static void1154struct_member_matrix_stride_cb(struct vtn_builder *b,1155UNUSED struct vtn_value *val, int member,1156const struct vtn_decoration *dec,1157void *void_ctx)1158{1159if (dec->decoration != SpvDecorationMatrixStride)1160return;11611162vtn_fail_if(member < 0,1163"The MatrixStride decoration is only allowed on members "1164"of OpTypeStruct");1165vtn_fail_if(dec->operands[0] == 0, "MatrixStride must be non-zero");11661167struct member_decoration_ctx *ctx = void_ctx;11681169struct vtn_type *mat_type = mutable_matrix_member(b, ctx->type, member);1170if (mat_type->row_major) {1171mat_type->array_element = vtn_type_copy(b, mat_type->array_element);1172mat_type->stride = mat_type->array_element->stride;1173mat_type->array_element->stride = dec->operands[0];11741175mat_type->type = glsl_explicit_matrix_type(mat_type->type,1176dec->operands[0], true);1177mat_type->array_element->type = glsl_get_column_type(mat_type->type);1178} else {1179vtn_assert(mat_type->array_element->stride > 0);1180mat_type->stride = dec->operands[0];11811182mat_type->type = glsl_explicit_matrix_type(mat_type->type,1183dec->operands[0], false);1184}11851186/* Now that we've replaced the glsl_type with a properly strided matrix1187* type, rewrite the member type so that it's an array of the proper kind1188* of glsl_type.1189*/1190vtn_array_type_rewrite_glsl_type(ctx->type->members[member]);1191ctx->fields[member].type = ctx->type->members[member]->type;1192}11931194static void1195struct_packed_decoration_cb(struct vtn_builder *b,1196struct vtn_value *val, int member,1197const struct vtn_decoration *dec, void *void_ctx)1198{1199vtn_assert(val->type->base_type == vtn_base_type_struct);1200if (dec->decoration == SpvDecorationCPacked) {1201if (b->shader->info.stage != MESA_SHADER_KERNEL) {1202vtn_warn("Decoration only allowed for CL-style kernels: %s",1203spirv_decoration_to_string(dec->decoration));1204}1205val->type->packed = true;1206}1207}12081209static void1210struct_block_decoration_cb(struct vtn_builder *b,1211struct vtn_value *val, int member,1212const struct vtn_decoration *dec, void *ctx)1213{1214if (member != -1)1215return;12161217struct vtn_type *type = val->type;1218if (dec->decoration == SpvDecorationBlock)1219type->block = true;1220else if (dec->decoration == SpvDecorationBufferBlock)1221type->buffer_block = true;1222}12231224static void1225type_decoration_cb(struct vtn_builder *b,1226struct vtn_value *val, int member,1227const struct vtn_decoration *dec, UNUSED void *ctx)1228{1229struct vtn_type *type = val->type;12301231if (member != -1) {1232/* This should have been handled by OpTypeStruct */1233assert(val->type->base_type == vtn_base_type_struct);1234assert(member >= 0 && member < val->type->length);1235return;1236}12371238switch (dec->decoration) {1239case SpvDecorationArrayStride:1240vtn_assert(type->base_type == vtn_base_type_array ||1241type->base_type == vtn_base_type_pointer);1242break;1243case SpvDecorationBlock:1244vtn_assert(type->base_type == vtn_base_type_struct);1245vtn_assert(type->block);1246break;1247case SpvDecorationBufferBlock:1248vtn_assert(type->base_type == vtn_base_type_struct);1249vtn_assert(type->buffer_block);1250break;1251case SpvDecorationGLSLShared:1252case SpvDecorationGLSLPacked:1253/* Ignore these, since we get explicit offsets anyways */1254break;12551256case SpvDecorationRowMajor:1257case SpvDecorationColMajor:1258case SpvDecorationMatrixStride:1259case SpvDecorationBuiltIn:1260case SpvDecorationNoPerspective:1261case SpvDecorationFlat:1262case SpvDecorationPatch:1263case SpvDecorationCentroid:1264case SpvDecorationSample:1265case SpvDecorationExplicitInterpAMD:1266case SpvDecorationVolatile:1267case SpvDecorationCoherent:1268case SpvDecorationNonWritable:1269case SpvDecorationNonReadable:1270case SpvDecorationUniform:1271case SpvDecorationUniformId:1272case SpvDecorationLocation:1273case SpvDecorationComponent:1274case SpvDecorationOffset:1275case SpvDecorationXfbBuffer:1276case SpvDecorationXfbStride:1277case SpvDecorationUserSemantic:1278vtn_warn("Decoration only allowed for struct members: %s",1279spirv_decoration_to_string(dec->decoration));1280break;12811282case SpvDecorationStream:1283/* We don't need to do anything here, as stream is filled up when1284* aplying the decoration to a variable, just check that if it is not a1285* struct member, it should be a struct.1286*/1287vtn_assert(type->base_type == vtn_base_type_struct);1288break;12891290case SpvDecorationRelaxedPrecision:1291case SpvDecorationSpecId:1292case SpvDecorationInvariant:1293case SpvDecorationRestrict:1294case SpvDecorationAliased:1295case SpvDecorationConstant:1296case SpvDecorationIndex:1297case SpvDecorationBinding:1298case SpvDecorationDescriptorSet:1299case SpvDecorationLinkageAttributes:1300case SpvDecorationNoContraction:1301case SpvDecorationInputAttachmentIndex:1302vtn_warn("Decoration not allowed on types: %s",1303spirv_decoration_to_string(dec->decoration));1304break;13051306case SpvDecorationCPacked:1307/* Handled when parsing a struct type, nothing to do here. */1308break;13091310case SpvDecorationSaturatedConversion:1311case SpvDecorationFuncParamAttr:1312case SpvDecorationFPRoundingMode:1313case SpvDecorationFPFastMathMode:1314case SpvDecorationAlignment:1315vtn_warn("Decoration only allowed for CL-style kernels: %s",1316spirv_decoration_to_string(dec->decoration));1317break;13181319case SpvDecorationUserTypeGOOGLE:1320/* User semantic decorations can safely be ignored by the driver. */1321break;13221323default:1324vtn_fail_with_decoration("Unhandled decoration", dec->decoration);1325}1326}13271328static unsigned1329translate_image_format(struct vtn_builder *b, SpvImageFormat format)1330{1331switch (format) {1332case SpvImageFormatUnknown: return PIPE_FORMAT_NONE;1333case SpvImageFormatRgba32f: return PIPE_FORMAT_R32G32B32A32_FLOAT;1334case SpvImageFormatRgba16f: return PIPE_FORMAT_R16G16B16A16_FLOAT;1335case SpvImageFormatR32f: return PIPE_FORMAT_R32_FLOAT;1336case SpvImageFormatRgba8: return PIPE_FORMAT_R8G8B8A8_UNORM;1337case SpvImageFormatRgba8Snorm: return PIPE_FORMAT_R8G8B8A8_SNORM;1338case SpvImageFormatRg32f: return PIPE_FORMAT_R32G32_FLOAT;1339case SpvImageFormatRg16f: return PIPE_FORMAT_R16G16_FLOAT;1340case SpvImageFormatR11fG11fB10f: return PIPE_FORMAT_R11G11B10_FLOAT;1341case SpvImageFormatR16f: return PIPE_FORMAT_R16_FLOAT;1342case SpvImageFormatRgba16: return PIPE_FORMAT_R16G16B16A16_UNORM;1343case SpvImageFormatRgb10A2: return PIPE_FORMAT_R10G10B10A2_UNORM;1344case SpvImageFormatRg16: return PIPE_FORMAT_R16G16_UNORM;1345case SpvImageFormatRg8: return PIPE_FORMAT_R8G8_UNORM;1346case SpvImageFormatR16: return PIPE_FORMAT_R16_UNORM;1347case SpvImageFormatR8: return PIPE_FORMAT_R8_UNORM;1348case SpvImageFormatRgba16Snorm: return PIPE_FORMAT_R16G16B16A16_SNORM;1349case SpvImageFormatRg16Snorm: return PIPE_FORMAT_R16G16_SNORM;1350case SpvImageFormatRg8Snorm: return PIPE_FORMAT_R8G8_SNORM;1351case SpvImageFormatR16Snorm: return PIPE_FORMAT_R16_SNORM;1352case SpvImageFormatR8Snorm: return PIPE_FORMAT_R8_SNORM;1353case SpvImageFormatRgba32i: return PIPE_FORMAT_R32G32B32A32_SINT;1354case SpvImageFormatRgba16i: return PIPE_FORMAT_R16G16B16A16_SINT;1355case SpvImageFormatRgba8i: return PIPE_FORMAT_R8G8B8A8_SINT;1356case SpvImageFormatR32i: return PIPE_FORMAT_R32_SINT;1357case SpvImageFormatRg32i: return PIPE_FORMAT_R32G32_SINT;1358case SpvImageFormatRg16i: return PIPE_FORMAT_R16G16_SINT;1359case SpvImageFormatRg8i: return PIPE_FORMAT_R8G8_SINT;1360case SpvImageFormatR16i: return PIPE_FORMAT_R16_SINT;1361case SpvImageFormatR8i: return PIPE_FORMAT_R8_SINT;1362case SpvImageFormatRgba32ui: return PIPE_FORMAT_R32G32B32A32_UINT;1363case SpvImageFormatRgba16ui: return PIPE_FORMAT_R16G16B16A16_UINT;1364case SpvImageFormatRgba8ui: return PIPE_FORMAT_R8G8B8A8_UINT;1365case SpvImageFormatR32ui: return PIPE_FORMAT_R32_UINT;1366case SpvImageFormatRgb10a2ui: return PIPE_FORMAT_R10G10B10A2_UINT;1367case SpvImageFormatRg32ui: return PIPE_FORMAT_R32G32_UINT;1368case SpvImageFormatRg16ui: return PIPE_FORMAT_R16G16_UINT;1369case SpvImageFormatRg8ui: return PIPE_FORMAT_R8G8_UINT;1370case SpvImageFormatR16ui: return PIPE_FORMAT_R16_UINT;1371case SpvImageFormatR8ui: return PIPE_FORMAT_R8_UINT;1372case SpvImageFormatR64ui: return PIPE_FORMAT_R64_UINT;1373case SpvImageFormatR64i: return PIPE_FORMAT_R64_SINT;1374default:1375vtn_fail("Invalid image format: %s (%u)",1376spirv_imageformat_to_string(format), format);1377}1378}13791380static void1381vtn_handle_type(struct vtn_builder *b, SpvOp opcode,1382const uint32_t *w, unsigned count)1383{1384struct vtn_value *val = NULL;13851386/* In order to properly handle forward declarations, we have to defer1387* allocation for pointer types.1388*/1389if (opcode != SpvOpTypePointer && opcode != SpvOpTypeForwardPointer) {1390val = vtn_push_value(b, w[1], vtn_value_type_type);1391vtn_fail_if(val->type != NULL,1392"Only pointers can have forward declarations");1393val->type = rzalloc(b, struct vtn_type);1394val->type->id = w[1];1395}13961397switch (opcode) {1398case SpvOpTypeVoid:1399val->type->base_type = vtn_base_type_void;1400val->type->type = glsl_void_type();1401break;1402case SpvOpTypeBool:1403val->type->base_type = vtn_base_type_scalar;1404val->type->type = glsl_bool_type();1405val->type->length = 1;1406break;1407case SpvOpTypeInt: {1408int bit_size = w[2];1409const bool signedness = w[3];1410vtn_fail_if(bit_size != 8 && bit_size != 16 &&1411bit_size != 32 && bit_size != 64,1412"Invalid int bit size: %u", bit_size);1413val->type->base_type = vtn_base_type_scalar;1414val->type->type = signedness ? glsl_intN_t_type(bit_size) :1415glsl_uintN_t_type(bit_size);1416val->type->length = 1;1417break;1418}14191420case SpvOpTypeFloat: {1421int bit_size = w[2];1422val->type->base_type = vtn_base_type_scalar;1423vtn_fail_if(bit_size != 16 && bit_size != 32 && bit_size != 64,1424"Invalid float bit size: %u", bit_size);1425val->type->type = glsl_floatN_t_type(bit_size);1426val->type->length = 1;1427break;1428}14291430case SpvOpTypeVector: {1431struct vtn_type *base = vtn_get_type(b, w[2]);1432unsigned elems = w[3];14331434vtn_fail_if(base->base_type != vtn_base_type_scalar,1435"Base type for OpTypeVector must be a scalar");1436vtn_fail_if((elems < 2 || elems > 4) && (elems != 8) && (elems != 16),1437"Invalid component count for OpTypeVector");14381439val->type->base_type = vtn_base_type_vector;1440val->type->type = glsl_vector_type(glsl_get_base_type(base->type), elems);1441val->type->length = elems;1442val->type->stride = glsl_type_is_boolean(val->type->type)1443? 4 : glsl_get_bit_size(base->type) / 8;1444val->type->array_element = base;1445break;1446}14471448case SpvOpTypeMatrix: {1449struct vtn_type *base = vtn_get_type(b, w[2]);1450unsigned columns = w[3];14511452vtn_fail_if(base->base_type != vtn_base_type_vector,1453"Base type for OpTypeMatrix must be a vector");1454vtn_fail_if(columns < 2 || columns > 4,1455"Invalid column count for OpTypeMatrix");14561457val->type->base_type = vtn_base_type_matrix;1458val->type->type = glsl_matrix_type(glsl_get_base_type(base->type),1459glsl_get_vector_elements(base->type),1460columns);1461vtn_fail_if(glsl_type_is_error(val->type->type),1462"Unsupported base type for OpTypeMatrix");1463assert(!glsl_type_is_error(val->type->type));1464val->type->length = columns;1465val->type->array_element = base;1466val->type->row_major = false;1467val->type->stride = 0;1468break;1469}14701471case SpvOpTypeRuntimeArray:1472case SpvOpTypeArray: {1473struct vtn_type *array_element = vtn_get_type(b, w[2]);14741475if (opcode == SpvOpTypeRuntimeArray) {1476/* A length of 0 is used to denote unsized arrays */1477val->type->length = 0;1478} else {1479val->type->length = vtn_constant_uint(b, w[3]);1480}14811482val->type->base_type = vtn_base_type_array;1483val->type->array_element = array_element;14841485vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL);1486val->type->type = glsl_array_type(array_element->type, val->type->length,1487val->type->stride);1488break;1489}14901491case SpvOpTypeStruct: {1492unsigned num_fields = count - 2;1493val->type->base_type = vtn_base_type_struct;1494val->type->length = num_fields;1495val->type->members = ralloc_array(b, struct vtn_type *, num_fields);1496val->type->offsets = ralloc_array(b, unsigned, num_fields);1497val->type->packed = false;14981499NIR_VLA(struct glsl_struct_field, fields, count);1500for (unsigned i = 0; i < num_fields; i++) {1501val->type->members[i] = vtn_get_type(b, w[i + 2]);1502fields[i] = (struct glsl_struct_field) {1503.type = val->type->members[i]->type,1504.name = ralloc_asprintf(b, "field%d", i),1505.location = -1,1506.offset = -1,1507};1508}15091510vtn_foreach_decoration(b, val, struct_packed_decoration_cb, NULL);15111512struct member_decoration_ctx ctx = {1513.num_fields = num_fields,1514.fields = fields,1515.type = val->type1516};15171518vtn_foreach_decoration(b, val, struct_member_decoration_cb, &ctx);15191520/* Propagate access specifiers that are present on all members to the overall type */1521enum gl_access_qualifier overall_access = ACCESS_COHERENT | ACCESS_VOLATILE |1522ACCESS_NON_READABLE | ACCESS_NON_WRITEABLE;1523for (unsigned i = 0; i < num_fields; ++i)1524overall_access &= val->type->members[i]->access;1525val->type->access = overall_access;15261527vtn_foreach_decoration(b, val, struct_member_matrix_stride_cb, &ctx);15281529vtn_foreach_decoration(b, val, struct_block_decoration_cb, NULL);15301531const char *name = val->name;15321533if (val->type->block || val->type->buffer_block) {1534/* Packing will be ignored since types coming from SPIR-V are1535* explicitly laid out.1536*/1537val->type->type = glsl_interface_type(fields, num_fields,1538/* packing */ 0, false,1539name ? name : "block");1540} else {1541val->type->type = glsl_struct_type(fields, num_fields,1542name ? name : "struct",1543val->type->packed);1544}1545break;1546}15471548case SpvOpTypeFunction: {1549val->type->base_type = vtn_base_type_function;1550val->type->type = NULL;15511552val->type->return_type = vtn_get_type(b, w[2]);15531554const unsigned num_params = count - 3;1555val->type->length = num_params;1556val->type->params = ralloc_array(b, struct vtn_type *, num_params);1557for (unsigned i = 0; i < count - 3; i++) {1558val->type->params[i] = vtn_get_type(b, w[i + 3]);1559}1560break;1561}15621563case SpvOpTypePointer:1564case SpvOpTypeForwardPointer: {1565/* We can't blindly push the value because it might be a forward1566* declaration.1567*/1568val = vtn_untyped_value(b, w[1]);15691570SpvStorageClass storage_class = w[2];15711572vtn_fail_if(opcode == SpvOpTypeForwardPointer &&1573b->shader->info.stage != MESA_SHADER_KERNEL &&1574storage_class != SpvStorageClassPhysicalStorageBuffer,1575"OpTypeForwardPointer is only allowed in Vulkan with "1576"the PhysicalStorageBuffer storage class");15771578struct vtn_type *deref_type = NULL;1579if (opcode == SpvOpTypePointer)1580deref_type = vtn_get_type(b, w[3]);15811582if (val->value_type == vtn_value_type_invalid) {1583val->value_type = vtn_value_type_type;1584val->type = rzalloc(b, struct vtn_type);1585val->type->id = w[1];1586val->type->base_type = vtn_base_type_pointer;1587val->type->storage_class = storage_class;15881589/* These can actually be stored to nir_variables and used as SSA1590* values so they need a real glsl_type.1591*/1592enum vtn_variable_mode mode = vtn_storage_class_to_mode(1593b, storage_class, deref_type, NULL);15941595/* The deref type should only matter for the UniformConstant storage1596* class. In particular, it should never matter for any storage1597* classes that are allowed in combination with OpTypeForwardPointer.1598*/1599if (storage_class != SpvStorageClassUniform &&1600storage_class != SpvStorageClassUniformConstant) {1601assert(mode == vtn_storage_class_to_mode(b, storage_class,1602NULL, NULL));1603}16041605val->type->type = nir_address_format_to_glsl_type(1606vtn_mode_to_address_format(b, mode));1607} else {1608vtn_fail_if(val->type->storage_class != storage_class,1609"The storage classes of an OpTypePointer and any "1610"OpTypeForwardPointers that provide forward "1611"declarations of it must match.");1612}16131614if (opcode == SpvOpTypePointer) {1615vtn_fail_if(val->type->deref != NULL,1616"While OpTypeForwardPointer can be used to provide a "1617"forward declaration of a pointer, OpTypePointer can "1618"only be used once for a given id.");16191620val->type->deref = deref_type;16211622/* Only certain storage classes use ArrayStride. */1623switch (storage_class) {1624case SpvStorageClassWorkgroup:1625if (!b->options->caps.workgroup_memory_explicit_layout)1626break;1627FALLTHROUGH;16281629case SpvStorageClassUniform:1630case SpvStorageClassPushConstant:1631case SpvStorageClassStorageBuffer:1632case SpvStorageClassPhysicalStorageBuffer:1633vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL);1634break;16351636default:1637/* Nothing to do. */1638break;1639}1640}1641break;1642}16431644case SpvOpTypeImage: {1645val->type->base_type = vtn_base_type_image;16461647/* Images are represented in NIR as a scalar SSA value that is the1648* result of a deref instruction. An OpLoad on an OpTypeImage pointer1649* from UniformConstant memory just takes the NIR deref from the pointer1650* and turns it into an SSA value.1651*/1652val->type->type = nir_address_format_to_glsl_type(1653vtn_mode_to_address_format(b, vtn_variable_mode_function));16541655const struct vtn_type *sampled_type = vtn_get_type(b, w[2]);1656if (b->shader->info.stage == MESA_SHADER_KERNEL) {1657vtn_fail_if(sampled_type->base_type != vtn_base_type_void,1658"Sampled type of OpTypeImage must be void for kernels");1659} else {1660vtn_fail_if(sampled_type->base_type != vtn_base_type_scalar,1661"Sampled type of OpTypeImage must be a scalar");1662if (b->options->caps.image_atomic_int64) {1663vtn_fail_if(glsl_get_bit_size(sampled_type->type) != 32 &&1664glsl_get_bit_size(sampled_type->type) != 64,1665"Sampled type of OpTypeImage must be a 32 or 64-bit "1666"scalar");1667} else {1668vtn_fail_if(glsl_get_bit_size(sampled_type->type) != 32,1669"Sampled type of OpTypeImage must be a 32-bit scalar");1670}1671}16721673enum glsl_sampler_dim dim;1674switch ((SpvDim)w[3]) {1675case SpvDim1D: dim = GLSL_SAMPLER_DIM_1D; break;1676case SpvDim2D: dim = GLSL_SAMPLER_DIM_2D; break;1677case SpvDim3D: dim = GLSL_SAMPLER_DIM_3D; break;1678case SpvDimCube: dim = GLSL_SAMPLER_DIM_CUBE; break;1679case SpvDimRect: dim = GLSL_SAMPLER_DIM_RECT; break;1680case SpvDimBuffer: dim = GLSL_SAMPLER_DIM_BUF; break;1681case SpvDimSubpassData: dim = GLSL_SAMPLER_DIM_SUBPASS; break;1682default:1683vtn_fail("Invalid SPIR-V image dimensionality: %s (%u)",1684spirv_dim_to_string((SpvDim)w[3]), w[3]);1685}16861687/* w[4]: as per Vulkan spec "Validation Rules within a Module",1688* The “Depth” operand of OpTypeImage is ignored.1689*/1690bool is_array = w[5];1691bool multisampled = w[6];1692unsigned sampled = w[7];1693SpvImageFormat format = w[8];16941695if (count > 9)1696val->type->access_qualifier = w[9];1697else if (b->shader->info.stage == MESA_SHADER_KERNEL)1698/* Per the CL C spec: If no qualifier is provided, read_only is assumed. */1699val->type->access_qualifier = SpvAccessQualifierReadOnly;1700else1701val->type->access_qualifier = SpvAccessQualifierReadWrite;17021703if (multisampled) {1704if (dim == GLSL_SAMPLER_DIM_2D)1705dim = GLSL_SAMPLER_DIM_MS;1706else if (dim == GLSL_SAMPLER_DIM_SUBPASS)1707dim = GLSL_SAMPLER_DIM_SUBPASS_MS;1708else1709vtn_fail("Unsupported multisampled image type");1710}17111712val->type->image_format = translate_image_format(b, format);17131714enum glsl_base_type sampled_base_type =1715glsl_get_base_type(sampled_type->type);1716if (sampled == 1) {1717val->type->glsl_image = glsl_sampler_type(dim, false, is_array,1718sampled_base_type);1719} else if (sampled == 2) {1720val->type->glsl_image = glsl_image_type(dim, is_array,1721sampled_base_type);1722} else if (b->shader->info.stage == MESA_SHADER_KERNEL) {1723val->type->glsl_image = glsl_image_type(dim, is_array,1724GLSL_TYPE_VOID);1725} else {1726vtn_fail("We need to know if the image will be sampled");1727}1728break;1729}17301731case SpvOpTypeSampledImage: {1732val->type->base_type = vtn_base_type_sampled_image;1733val->type->image = vtn_get_type(b, w[2]);17341735/* Sampled images are represented NIR as a vec2 SSA value where each1736* component is the result of a deref instruction. The first component1737* is the image and the second is the sampler. An OpLoad on an1738* OpTypeSampledImage pointer from UniformConstant memory just takes1739* the NIR deref from the pointer and duplicates it to both vector1740* components.1741*/1742nir_address_format addr_format =1743vtn_mode_to_address_format(b, vtn_variable_mode_function);1744assert(nir_address_format_num_components(addr_format) == 1);1745unsigned bit_size = nir_address_format_bit_size(addr_format);1746assert(bit_size == 32 || bit_size == 64);17471748enum glsl_base_type base_type =1749bit_size == 32 ? GLSL_TYPE_UINT : GLSL_TYPE_UINT64;1750val->type->type = glsl_vector_type(base_type, 2);1751break;1752}17531754case SpvOpTypeSampler:1755val->type->base_type = vtn_base_type_sampler;17561757/* Samplers are represented in NIR as a scalar SSA value that is the1758* result of a deref instruction. An OpLoad on an OpTypeSampler pointer1759* from UniformConstant memory just takes the NIR deref from the pointer1760* and turns it into an SSA value.1761*/1762val->type->type = nir_address_format_to_glsl_type(1763vtn_mode_to_address_format(b, vtn_variable_mode_function));1764break;17651766case SpvOpTypeAccelerationStructureKHR:1767val->type->base_type = vtn_base_type_accel_struct;1768val->type->type = glsl_uint64_t_type();1769break;17701771case SpvOpTypeOpaque:1772val->type->base_type = vtn_base_type_struct;1773const char *name = vtn_string_literal(b, &w[2], count - 2, NULL);1774val->type->type = glsl_struct_type(NULL, 0, name, false);1775break;17761777case SpvOpTypeEvent:1778val->type->base_type = vtn_base_type_event;1779val->type->type = glsl_int_type();1780break;17811782case SpvOpTypeDeviceEvent:1783case SpvOpTypeReserveId:1784case SpvOpTypeQueue:1785case SpvOpTypePipe:1786default:1787vtn_fail_with_opcode("Unhandled opcode", opcode);1788}17891790vtn_foreach_decoration(b, val, type_decoration_cb, NULL);17911792if (val->type->base_type == vtn_base_type_struct &&1793(val->type->block || val->type->buffer_block)) {1794for (unsigned i = 0; i < val->type->length; i++) {1795vtn_fail_if(vtn_type_contains_block(b, val->type->members[i]),1796"Block and BufferBlock decorations cannot decorate a "1797"structure type that is nested at any level inside "1798"another structure type decorated with Block or "1799"BufferBlock.");1800}1801}1802}18031804static nir_constant *1805vtn_null_constant(struct vtn_builder *b, struct vtn_type *type)1806{1807nir_constant *c = rzalloc(b, nir_constant);18081809switch (type->base_type) {1810case vtn_base_type_scalar:1811case vtn_base_type_vector:1812/* Nothing to do here. It's already initialized to zero */1813break;18141815case vtn_base_type_pointer: {1816enum vtn_variable_mode mode = vtn_storage_class_to_mode(1817b, type->storage_class, type->deref, NULL);1818nir_address_format addr_format = vtn_mode_to_address_format(b, mode);18191820const nir_const_value *null_value = nir_address_format_null_value(addr_format);1821memcpy(c->values, null_value,1822sizeof(nir_const_value) * nir_address_format_num_components(addr_format));1823break;1824}18251826case vtn_base_type_void:1827case vtn_base_type_image:1828case vtn_base_type_sampler:1829case vtn_base_type_sampled_image:1830case vtn_base_type_function:1831case vtn_base_type_event:1832/* For those we have to return something but it doesn't matter what. */1833break;18341835case vtn_base_type_matrix:1836case vtn_base_type_array:1837vtn_assert(type->length > 0);1838c->num_elements = type->length;1839c->elements = ralloc_array(b, nir_constant *, c->num_elements);18401841c->elements[0] = vtn_null_constant(b, type->array_element);1842for (unsigned i = 1; i < c->num_elements; i++)1843c->elements[i] = c->elements[0];1844break;18451846case vtn_base_type_struct:1847c->num_elements = type->length;1848c->elements = ralloc_array(b, nir_constant *, c->num_elements);1849for (unsigned i = 0; i < c->num_elements; i++)1850c->elements[i] = vtn_null_constant(b, type->members[i]);1851break;18521853default:1854vtn_fail("Invalid type for null constant");1855}18561857return c;1858}18591860static void1861spec_constant_decoration_cb(struct vtn_builder *b, UNUSED struct vtn_value *val,1862ASSERTED int member,1863const struct vtn_decoration *dec, void *data)1864{1865vtn_assert(member == -1);1866if (dec->decoration != SpvDecorationSpecId)1867return;18681869nir_const_value *value = data;1870for (unsigned i = 0; i < b->num_specializations; i++) {1871if (b->specializations[i].id == dec->operands[0]) {1872*value = b->specializations[i].value;1873return;1874}1875}1876}18771878static void1879handle_workgroup_size_decoration_cb(struct vtn_builder *b,1880struct vtn_value *val,1881ASSERTED int member,1882const struct vtn_decoration *dec,1883UNUSED void *data)1884{1885vtn_assert(member == -1);1886if (dec->decoration != SpvDecorationBuiltIn ||1887dec->operands[0] != SpvBuiltInWorkgroupSize)1888return;18891890vtn_assert(val->type->type == glsl_vector_type(GLSL_TYPE_UINT, 3));1891b->workgroup_size_builtin = val;1892}18931894static void1895vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,1896const uint32_t *w, unsigned count)1897{1898struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant);1899val->constant = rzalloc(b, nir_constant);1900switch (opcode) {1901case SpvOpConstantTrue:1902case SpvOpConstantFalse:1903case SpvOpSpecConstantTrue:1904case SpvOpSpecConstantFalse: {1905vtn_fail_if(val->type->type != glsl_bool_type(),1906"Result type of %s must be OpTypeBool",1907spirv_op_to_string(opcode));19081909bool bval = (opcode == SpvOpConstantTrue ||1910opcode == SpvOpSpecConstantTrue);19111912nir_const_value u32val = nir_const_value_for_uint(bval, 32);19131914if (opcode == SpvOpSpecConstantTrue ||1915opcode == SpvOpSpecConstantFalse)1916vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &u32val);19171918val->constant->values[0].b = u32val.u32 != 0;1919break;1920}19211922case SpvOpConstant:1923case SpvOpSpecConstant: {1924vtn_fail_if(val->type->base_type != vtn_base_type_scalar,1925"Result type of %s must be a scalar",1926spirv_op_to_string(opcode));1927int bit_size = glsl_get_bit_size(val->type->type);1928switch (bit_size) {1929case 64:1930val->constant->values[0].u64 = vtn_u64_literal(&w[3]);1931break;1932case 32:1933val->constant->values[0].u32 = w[3];1934break;1935case 16:1936val->constant->values[0].u16 = w[3];1937break;1938case 8:1939val->constant->values[0].u8 = w[3];1940break;1941default:1942vtn_fail("Unsupported SpvOpConstant bit size: %u", bit_size);1943}19441945if (opcode == SpvOpSpecConstant)1946vtn_foreach_decoration(b, val, spec_constant_decoration_cb,1947&val->constant->values[0]);1948break;1949}19501951case SpvOpSpecConstantComposite:1952case SpvOpConstantComposite: {1953unsigned elem_count = count - 3;1954vtn_fail_if(elem_count != val->type->length,1955"%s has %u constituents, expected %u",1956spirv_op_to_string(opcode), elem_count, val->type->length);19571958nir_constant **elems = ralloc_array(b, nir_constant *, elem_count);1959for (unsigned i = 0; i < elem_count; i++) {1960struct vtn_value *val = vtn_untyped_value(b, w[i + 3]);19611962if (val->value_type == vtn_value_type_constant) {1963elems[i] = val->constant;1964} else {1965vtn_fail_if(val->value_type != vtn_value_type_undef,1966"only constants or undefs allowed for "1967"SpvOpConstantComposite");1968/* to make it easier, just insert a NULL constant for now */1969elems[i] = vtn_null_constant(b, val->type);1970}1971}19721973switch (val->type->base_type) {1974case vtn_base_type_vector: {1975assert(glsl_type_is_vector(val->type->type));1976for (unsigned i = 0; i < elem_count; i++)1977val->constant->values[i] = elems[i]->values[0];1978break;1979}19801981case vtn_base_type_matrix:1982case vtn_base_type_struct:1983case vtn_base_type_array:1984ralloc_steal(val->constant, elems);1985val->constant->num_elements = elem_count;1986val->constant->elements = elems;1987break;19881989default:1990vtn_fail("Result type of %s must be a composite type",1991spirv_op_to_string(opcode));1992}1993break;1994}19951996case SpvOpSpecConstantOp: {1997nir_const_value u32op = nir_const_value_for_uint(w[3], 32);1998vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &u32op);1999SpvOp opcode = u32op.u32;2000switch (opcode) {2001case SpvOpVectorShuffle: {2002struct vtn_value *v0 = &b->values[w[4]];2003struct vtn_value *v1 = &b->values[w[5]];20042005vtn_assert(v0->value_type == vtn_value_type_constant ||2006v0->value_type == vtn_value_type_undef);2007vtn_assert(v1->value_type == vtn_value_type_constant ||2008v1->value_type == vtn_value_type_undef);20092010unsigned len0 = glsl_get_vector_elements(v0->type->type);2011unsigned len1 = glsl_get_vector_elements(v1->type->type);20122013vtn_assert(len0 + len1 < 16);20142015unsigned bit_size = glsl_get_bit_size(val->type->type);2016unsigned bit_size0 = glsl_get_bit_size(v0->type->type);2017unsigned bit_size1 = glsl_get_bit_size(v1->type->type);20182019vtn_assert(bit_size == bit_size0 && bit_size == bit_size1);2020(void)bit_size0; (void)bit_size1;20212022nir_const_value undef = { .u64 = 0xdeadbeefdeadbeef };2023nir_const_value combined[NIR_MAX_VEC_COMPONENTS * 2];20242025if (v0->value_type == vtn_value_type_constant) {2026for (unsigned i = 0; i < len0; i++)2027combined[i] = v0->constant->values[i];2028}2029if (v1->value_type == vtn_value_type_constant) {2030for (unsigned i = 0; i < len1; i++)2031combined[len0 + i] = v1->constant->values[i];2032}20332034for (unsigned i = 0, j = 0; i < count - 6; i++, j++) {2035uint32_t comp = w[i + 6];2036if (comp == (uint32_t)-1) {2037/* If component is not used, set the value to a known constant2038* to detect if it is wrongly used.2039*/2040val->constant->values[j] = undef;2041} else {2042vtn_fail_if(comp >= len0 + len1,2043"All Component literals must either be FFFFFFFF "2044"or in [0, N - 1] (inclusive).");2045val->constant->values[j] = combined[comp];2046}2047}2048break;2049}20502051case SpvOpCompositeExtract:2052case SpvOpCompositeInsert: {2053struct vtn_value *comp;2054unsigned deref_start;2055struct nir_constant **c;2056if (opcode == SpvOpCompositeExtract) {2057comp = vtn_value(b, w[4], vtn_value_type_constant);2058deref_start = 5;2059c = &comp->constant;2060} else {2061comp = vtn_value(b, w[5], vtn_value_type_constant);2062deref_start = 6;2063val->constant = nir_constant_clone(comp->constant,2064(nir_variable *)b);2065c = &val->constant;2066}20672068int elem = -1;2069const struct vtn_type *type = comp->type;2070for (unsigned i = deref_start; i < count; i++) {2071vtn_fail_if(w[i] > type->length,2072"%uth index of %s is %u but the type has only "2073"%u elements", i - deref_start,2074spirv_op_to_string(opcode), w[i], type->length);20752076switch (type->base_type) {2077case vtn_base_type_vector:2078elem = w[i];2079type = type->array_element;2080break;20812082case vtn_base_type_matrix:2083case vtn_base_type_array:2084c = &(*c)->elements[w[i]];2085type = type->array_element;2086break;20872088case vtn_base_type_struct:2089c = &(*c)->elements[w[i]];2090type = type->members[w[i]];2091break;20922093default:2094vtn_fail("%s must only index into composite types",2095spirv_op_to_string(opcode));2096}2097}20982099if (opcode == SpvOpCompositeExtract) {2100if (elem == -1) {2101val->constant = *c;2102} else {2103unsigned num_components = type->length;2104for (unsigned i = 0; i < num_components; i++)2105val->constant->values[i] = (*c)->values[elem + i];2106}2107} else {2108struct vtn_value *insert =2109vtn_value(b, w[4], vtn_value_type_constant);2110vtn_assert(insert->type == type);2111if (elem == -1) {2112*c = insert->constant;2113} else {2114unsigned num_components = type->length;2115for (unsigned i = 0; i < num_components; i++)2116(*c)->values[elem + i] = insert->constant->values[i];2117}2118}2119break;2120}21212122default: {2123bool swap;2124nir_alu_type dst_alu_type = nir_get_nir_type_for_glsl_type(val->type->type);2125nir_alu_type src_alu_type = dst_alu_type;2126unsigned num_components = glsl_get_vector_elements(val->type->type);2127unsigned bit_size;21282129vtn_assert(count <= 7);21302131switch (opcode) {2132case SpvOpSConvert:2133case SpvOpFConvert:2134case SpvOpUConvert:2135/* We have a source in a conversion */2136src_alu_type =2137nir_get_nir_type_for_glsl_type(vtn_get_value_type(b, w[4])->type);2138/* We use the bitsize of the conversion source to evaluate the opcode later */2139bit_size = glsl_get_bit_size(vtn_get_value_type(b, w[4])->type);2140break;2141default:2142bit_size = glsl_get_bit_size(val->type->type);2143};21442145bool exact;2146nir_op op = vtn_nir_alu_op_for_spirv_opcode(b, opcode, &swap, &exact,2147nir_alu_type_get_type_size(src_alu_type),2148nir_alu_type_get_type_size(dst_alu_type));21492150/* No SPIR-V opcodes handled through this path should set exact.2151* Since it is ignored, assert on it.2152*/2153assert(!exact);21542155nir_const_value src[3][NIR_MAX_VEC_COMPONENTS];21562157for (unsigned i = 0; i < count - 4; i++) {2158struct vtn_value *src_val =2159vtn_value(b, w[4 + i], vtn_value_type_constant);21602161/* If this is an unsized source, pull the bit size from the2162* source; otherwise, we'll use the bit size from the destination.2163*/2164if (!nir_alu_type_get_type_size(nir_op_infos[op].input_types[i]))2165bit_size = glsl_get_bit_size(src_val->type->type);21662167unsigned src_comps = nir_op_infos[op].input_sizes[i] ?2168nir_op_infos[op].input_sizes[i] :2169num_components;21702171unsigned j = swap ? 1 - i : i;2172for (unsigned c = 0; c < src_comps; c++)2173src[j][c] = src_val->constant->values[c];2174}21752176/* fix up fixed size sources */2177switch (op) {2178case nir_op_ishl:2179case nir_op_ishr:2180case nir_op_ushr: {2181if (bit_size == 32)2182break;2183for (unsigned i = 0; i < num_components; ++i) {2184switch (bit_size) {2185case 64: src[1][i].u32 = src[1][i].u64; break;2186case 16: src[1][i].u32 = src[1][i].u16; break;2187case 8: src[1][i].u32 = src[1][i].u8; break;2188}2189}2190break;2191}2192default:2193break;2194}21952196nir_const_value *srcs[3] = {2197src[0], src[1], src[2],2198};2199nir_eval_const_opcode(op, val->constant->values,2200num_components, bit_size, srcs,2201b->shader->info.float_controls_execution_mode);2202break;2203} /* default */2204}2205break;2206}22072208case SpvOpConstantNull:2209val->constant = vtn_null_constant(b, val->type);2210val->is_null_constant = true;2211break;22122213default:2214vtn_fail_with_opcode("Unhandled opcode", opcode);2215}22162217/* Now that we have the value, update the workgroup size if needed */2218if (b->entry_point_stage == MESA_SHADER_COMPUTE ||2219b->entry_point_stage == MESA_SHADER_KERNEL)2220vtn_foreach_decoration(b, val, handle_workgroup_size_decoration_cb,2221NULL);2222}22232224static void2225vtn_split_barrier_semantics(struct vtn_builder *b,2226SpvMemorySemanticsMask semantics,2227SpvMemorySemanticsMask *before,2228SpvMemorySemanticsMask *after)2229{2230/* For memory semantics embedded in operations, we split them into up to2231* two barriers, to be added before and after the operation. This is less2232* strict than if we propagated until the final backend stage, but still2233* result in correct execution.2234*2235* A further improvement could be pipe this information (and use!) into the2236* next compiler layers, at the expense of making the handling of barriers2237* more complicated.2238*/22392240*before = SpvMemorySemanticsMaskNone;2241*after = SpvMemorySemanticsMaskNone;22422243SpvMemorySemanticsMask order_semantics =2244semantics & (SpvMemorySemanticsAcquireMask |2245SpvMemorySemanticsReleaseMask |2246SpvMemorySemanticsAcquireReleaseMask |2247SpvMemorySemanticsSequentiallyConsistentMask);22482249if (util_bitcount(order_semantics) > 1) {2250/* Old GLSLang versions incorrectly set all the ordering bits. This was2251* fixed in c51287d744fb6e7e9ccc09f6f8451e6c64b1dad6 of glslang repo,2252* and it is in GLSLang since revision "SPIRV99.1321" (from Jul-2016).2253*/2254vtn_warn("Multiple memory ordering semantics specified, "2255"assuming AcquireRelease.");2256order_semantics = SpvMemorySemanticsAcquireReleaseMask;2257}22582259const SpvMemorySemanticsMask av_vis_semantics =2260semantics & (SpvMemorySemanticsMakeAvailableMask |2261SpvMemorySemanticsMakeVisibleMask);22622263const SpvMemorySemanticsMask storage_semantics =2264semantics & (SpvMemorySemanticsUniformMemoryMask |2265SpvMemorySemanticsSubgroupMemoryMask |2266SpvMemorySemanticsWorkgroupMemoryMask |2267SpvMemorySemanticsCrossWorkgroupMemoryMask |2268SpvMemorySemanticsAtomicCounterMemoryMask |2269SpvMemorySemanticsImageMemoryMask |2270SpvMemorySemanticsOutputMemoryMask);22712272const SpvMemorySemanticsMask other_semantics =2273semantics & ~(order_semantics | av_vis_semantics | storage_semantics |2274SpvMemorySemanticsVolatileMask);22752276if (other_semantics)2277vtn_warn("Ignoring unhandled memory semantics: %u\n", other_semantics);22782279/* SequentiallyConsistent is treated as AcquireRelease. */22802281/* The RELEASE barrier happens BEFORE the operation, and it is usually2282* associated with a Store. All the write operations with a matching2283* semantics will not be reordered after the Store.2284*/2285if (order_semantics & (SpvMemorySemanticsReleaseMask |2286SpvMemorySemanticsAcquireReleaseMask |2287SpvMemorySemanticsSequentiallyConsistentMask)) {2288*before |= SpvMemorySemanticsReleaseMask | storage_semantics;2289}22902291/* The ACQUIRE barrier happens AFTER the operation, and it is usually2292* associated with a Load. All the operations with a matching semantics2293* will not be reordered before the Load.2294*/2295if (order_semantics & (SpvMemorySemanticsAcquireMask |2296SpvMemorySemanticsAcquireReleaseMask |2297SpvMemorySemanticsSequentiallyConsistentMask)) {2298*after |= SpvMemorySemanticsAcquireMask | storage_semantics;2299}23002301if (av_vis_semantics & SpvMemorySemanticsMakeVisibleMask)2302*before |= SpvMemorySemanticsMakeVisibleMask | storage_semantics;23032304if (av_vis_semantics & SpvMemorySemanticsMakeAvailableMask)2305*after |= SpvMemorySemanticsMakeAvailableMask | storage_semantics;2306}23072308static nir_memory_semantics2309vtn_mem_semantics_to_nir_mem_semantics(struct vtn_builder *b,2310SpvMemorySemanticsMask semantics)2311{2312nir_memory_semantics nir_semantics = 0;23132314SpvMemorySemanticsMask order_semantics =2315semantics & (SpvMemorySemanticsAcquireMask |2316SpvMemorySemanticsReleaseMask |2317SpvMemorySemanticsAcquireReleaseMask |2318SpvMemorySemanticsSequentiallyConsistentMask);23192320if (util_bitcount(order_semantics) > 1) {2321/* Old GLSLang versions incorrectly set all the ordering bits. This was2322* fixed in c51287d744fb6e7e9ccc09f6f8451e6c64b1dad6 of glslang repo,2323* and it is in GLSLang since revision "SPIRV99.1321" (from Jul-2016).2324*/2325vtn_warn("Multiple memory ordering semantics bits specified, "2326"assuming AcquireRelease.");2327order_semantics = SpvMemorySemanticsAcquireReleaseMask;2328}23292330switch (order_semantics) {2331case 0:2332/* Not an ordering barrier. */2333break;23342335case SpvMemorySemanticsAcquireMask:2336nir_semantics = NIR_MEMORY_ACQUIRE;2337break;23382339case SpvMemorySemanticsReleaseMask:2340nir_semantics = NIR_MEMORY_RELEASE;2341break;23422343case SpvMemorySemanticsSequentiallyConsistentMask:2344FALLTHROUGH; /* Treated as AcquireRelease in Vulkan. */2345case SpvMemorySemanticsAcquireReleaseMask:2346nir_semantics = NIR_MEMORY_ACQUIRE | NIR_MEMORY_RELEASE;2347break;23482349default:2350unreachable("Invalid memory order semantics");2351}23522353if (semantics & SpvMemorySemanticsMakeAvailableMask) {2354vtn_fail_if(!b->options->caps.vk_memory_model,2355"To use MakeAvailable memory semantics the VulkanMemoryModel "2356"capability must be declared.");2357nir_semantics |= NIR_MEMORY_MAKE_AVAILABLE;2358}23592360if (semantics & SpvMemorySemanticsMakeVisibleMask) {2361vtn_fail_if(!b->options->caps.vk_memory_model,2362"To use MakeVisible memory semantics the VulkanMemoryModel "2363"capability must be declared.");2364nir_semantics |= NIR_MEMORY_MAKE_VISIBLE;2365}23662367return nir_semantics;2368}23692370static nir_variable_mode2371vtn_mem_semantics_to_nir_var_modes(struct vtn_builder *b,2372SpvMemorySemanticsMask semantics)2373{2374/* Vulkan Environment for SPIR-V says "SubgroupMemory, CrossWorkgroupMemory,2375* and AtomicCounterMemory are ignored".2376*/2377if (b->options->environment == NIR_SPIRV_VULKAN) {2378semantics &= ~(SpvMemorySemanticsSubgroupMemoryMask |2379SpvMemorySemanticsCrossWorkgroupMemoryMask |2380SpvMemorySemanticsAtomicCounterMemoryMask);2381}23822383/* TODO: Consider adding nir_var_mem_image mode to NIR so it can be used2384* for SpvMemorySemanticsImageMemoryMask.2385*/23862387nir_variable_mode modes = 0;2388if (semantics & (SpvMemorySemanticsUniformMemoryMask |2389SpvMemorySemanticsImageMemoryMask)) {2390modes |= nir_var_uniform |2391nir_var_mem_ubo |2392nir_var_mem_ssbo |2393nir_var_mem_global;2394}2395if (semantics & SpvMemorySemanticsWorkgroupMemoryMask)2396modes |= nir_var_mem_shared;2397if (semantics & SpvMemorySemanticsCrossWorkgroupMemoryMask)2398modes |= nir_var_mem_global;2399if (semantics & SpvMemorySemanticsOutputMemoryMask) {2400modes |= nir_var_shader_out;2401}24022403return modes;2404}24052406static nir_scope2407vtn_scope_to_nir_scope(struct vtn_builder *b, SpvScope scope)2408{2409nir_scope nir_scope;2410switch (scope) {2411case SpvScopeDevice:2412vtn_fail_if(b->options->caps.vk_memory_model &&2413!b->options->caps.vk_memory_model_device_scope,2414"If the Vulkan memory model is declared and any instruction "2415"uses Device scope, the VulkanMemoryModelDeviceScope "2416"capability must be declared.");2417nir_scope = NIR_SCOPE_DEVICE;2418break;24192420case SpvScopeQueueFamily:2421vtn_fail_if(!b->options->caps.vk_memory_model,2422"To use Queue Family scope, the VulkanMemoryModel capability "2423"must be declared.");2424nir_scope = NIR_SCOPE_QUEUE_FAMILY;2425break;24262427case SpvScopeWorkgroup:2428nir_scope = NIR_SCOPE_WORKGROUP;2429break;24302431case SpvScopeSubgroup:2432nir_scope = NIR_SCOPE_SUBGROUP;2433break;24342435case SpvScopeInvocation:2436nir_scope = NIR_SCOPE_INVOCATION;2437break;24382439case SpvScopeShaderCallKHR:2440nir_scope = NIR_SCOPE_SHADER_CALL;2441break;24422443default:2444vtn_fail("Invalid memory scope");2445}24462447return nir_scope;2448}24492450static void2451vtn_emit_scoped_control_barrier(struct vtn_builder *b, SpvScope exec_scope,2452SpvScope mem_scope,2453SpvMemorySemanticsMask semantics)2454{2455nir_memory_semantics nir_semantics =2456vtn_mem_semantics_to_nir_mem_semantics(b, semantics);2457nir_variable_mode modes = vtn_mem_semantics_to_nir_var_modes(b, semantics);2458nir_scope nir_exec_scope = vtn_scope_to_nir_scope(b, exec_scope);24592460/* Memory semantics is optional for OpControlBarrier. */2461nir_scope nir_mem_scope;2462if (nir_semantics == 0 || modes == 0)2463nir_mem_scope = NIR_SCOPE_NONE;2464else2465nir_mem_scope = vtn_scope_to_nir_scope(b, mem_scope);24662467nir_scoped_barrier(&b->nb, .execution_scope=nir_exec_scope, .memory_scope=nir_mem_scope,2468.memory_semantics=nir_semantics, .memory_modes=modes);2469}24702471static void2472vtn_emit_scoped_memory_barrier(struct vtn_builder *b, SpvScope scope,2473SpvMemorySemanticsMask semantics)2474{2475nir_variable_mode modes = vtn_mem_semantics_to_nir_var_modes(b, semantics);2476nir_memory_semantics nir_semantics =2477vtn_mem_semantics_to_nir_mem_semantics(b, semantics);24782479/* No barrier to add. */2480if (nir_semantics == 0 || modes == 0)2481return;24822483nir_scoped_barrier(&b->nb, .memory_scope=vtn_scope_to_nir_scope(b, scope),2484.memory_semantics=nir_semantics,2485.memory_modes=modes);2486}24872488struct vtn_ssa_value *2489vtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type)2490{2491/* Always use bare types for SSA values for a couple of reasons:2492*2493* 1. Code which emits deref chains should never listen to the explicit2494* layout information on the SSA value if any exists. If we've2495* accidentally been relying on this, we want to find those bugs.2496*2497* 2. We want to be able to quickly check that an SSA value being assigned2498* to a SPIR-V value has the right type. Using bare types everywhere2499* ensures that we can pointer-compare.2500*/2501struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);2502val->type = glsl_get_bare_type(type);250325042505if (!glsl_type_is_vector_or_scalar(type)) {2506unsigned elems = glsl_get_length(val->type);2507val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);2508if (glsl_type_is_array_or_matrix(type)) {2509const struct glsl_type *elem_type = glsl_get_array_element(type);2510for (unsigned i = 0; i < elems; i++)2511val->elems[i] = vtn_create_ssa_value(b, elem_type);2512} else {2513vtn_assert(glsl_type_is_struct_or_ifc(type));2514for (unsigned i = 0; i < elems; i++) {2515const struct glsl_type *elem_type = glsl_get_struct_field(type, i);2516val->elems[i] = vtn_create_ssa_value(b, elem_type);2517}2518}2519}25202521return val;2522}25232524static nir_tex_src2525vtn_tex_src(struct vtn_builder *b, unsigned index, nir_tex_src_type type)2526{2527nir_tex_src src;2528src.src = nir_src_for_ssa(vtn_get_nir_ssa(b, index));2529src.src_type = type;2530return src;2531}25322533static uint32_t2534image_operand_arg(struct vtn_builder *b, const uint32_t *w, uint32_t count,2535uint32_t mask_idx, SpvImageOperandsMask op)2536{2537static const SpvImageOperandsMask ops_with_arg =2538SpvImageOperandsBiasMask |2539SpvImageOperandsLodMask |2540SpvImageOperandsGradMask |2541SpvImageOperandsConstOffsetMask |2542SpvImageOperandsOffsetMask |2543SpvImageOperandsConstOffsetsMask |2544SpvImageOperandsSampleMask |2545SpvImageOperandsMinLodMask |2546SpvImageOperandsMakeTexelAvailableMask |2547SpvImageOperandsMakeTexelVisibleMask;25482549assert(util_bitcount(op) == 1);2550assert(w[mask_idx] & op);2551assert(op & ops_with_arg);25522553uint32_t idx = util_bitcount(w[mask_idx] & (op - 1) & ops_with_arg) + 1;25542555/* Adjust indices for operands with two arguments. */2556static const SpvImageOperandsMask ops_with_two_args =2557SpvImageOperandsGradMask;2558idx += util_bitcount(w[mask_idx] & (op - 1) & ops_with_two_args);25592560idx += mask_idx;25612562vtn_fail_if(idx + (op & ops_with_two_args ? 1 : 0) >= count,2563"Image op claims to have %s but does not enough "2564"following operands", spirv_imageoperands_to_string(op));25652566return idx;2567}25682569static void2570non_uniform_decoration_cb(struct vtn_builder *b,2571struct vtn_value *val, int member,2572const struct vtn_decoration *dec, void *void_ctx)2573{2574enum gl_access_qualifier *access = void_ctx;2575switch (dec->decoration) {2576case SpvDecorationNonUniformEXT:2577*access |= ACCESS_NON_UNIFORM;2578break;25792580default:2581break;2582}2583}25842585/* Apply SignExtend/ZeroExtend operands to get the actual result type for2586* image read/sample operations and source type for write operations.2587*/2588static nir_alu_type2589get_image_type(struct vtn_builder *b, nir_alu_type type, unsigned operands)2590{2591unsigned extend_operands =2592operands & (SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask);2593vtn_fail_if(nir_alu_type_get_base_type(type) == nir_type_float && extend_operands,2594"SignExtend/ZeroExtend used on floating-point texel type");2595vtn_fail_if(extend_operands ==2596(SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask),2597"SignExtend and ZeroExtend both specified");25982599if (operands & SpvImageOperandsSignExtendMask)2600return nir_type_int | nir_alu_type_get_type_size(type);2601if (operands & SpvImageOperandsZeroExtendMask)2602return nir_type_uint | nir_alu_type_get_type_size(type);26032604return type;2605}26062607static void2608vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,2609const uint32_t *w, unsigned count)2610{2611if (opcode == SpvOpSampledImage) {2612struct vtn_sampled_image si = {2613.image = vtn_get_image(b, w[3], NULL),2614.sampler = vtn_get_sampler(b, w[4]),2615};26162617enum gl_access_qualifier access = 0;2618vtn_foreach_decoration(b, vtn_untyped_value(b, w[3]),2619non_uniform_decoration_cb, &access);2620vtn_foreach_decoration(b, vtn_untyped_value(b, w[4]),2621non_uniform_decoration_cb, &access);26222623vtn_push_sampled_image(b, w[2], si, access & ACCESS_NON_UNIFORM);2624return;2625} else if (opcode == SpvOpImage) {2626struct vtn_sampled_image si = vtn_get_sampled_image(b, w[3]);26272628enum gl_access_qualifier access = 0;2629vtn_foreach_decoration(b, vtn_untyped_value(b, w[3]),2630non_uniform_decoration_cb, &access);26312632vtn_push_image(b, w[2], si.image, access & ACCESS_NON_UNIFORM);2633return;2634} else if (opcode == SpvOpImageSparseTexelsResident) {2635nir_ssa_def *code = vtn_get_nir_ssa(b, w[3]);2636vtn_push_nir_ssa(b, w[2], nir_is_sparse_texels_resident(&b->nb, code));2637return;2638}26392640nir_deref_instr *image = NULL, *sampler = NULL;2641struct vtn_value *sampled_val = vtn_untyped_value(b, w[3]);2642if (sampled_val->type->base_type == vtn_base_type_sampled_image) {2643struct vtn_sampled_image si = vtn_get_sampled_image(b, w[3]);2644image = si.image;2645sampler = si.sampler;2646} else {2647image = vtn_get_image(b, w[3], NULL);2648}26492650const enum glsl_sampler_dim sampler_dim = glsl_get_sampler_dim(image->type);2651const bool is_array = glsl_sampler_type_is_array(image->type);2652nir_alu_type dest_type = nir_type_invalid;26532654/* Figure out the base texture operation */2655nir_texop texop;2656switch (opcode) {2657case SpvOpImageSampleImplicitLod:2658case SpvOpImageSparseSampleImplicitLod:2659case SpvOpImageSampleDrefImplicitLod:2660case SpvOpImageSparseSampleDrefImplicitLod:2661case SpvOpImageSampleProjImplicitLod:2662case SpvOpImageSampleProjDrefImplicitLod:2663texop = nir_texop_tex;2664break;26652666case SpvOpImageSampleExplicitLod:2667case SpvOpImageSparseSampleExplicitLod:2668case SpvOpImageSampleDrefExplicitLod:2669case SpvOpImageSparseSampleDrefExplicitLod:2670case SpvOpImageSampleProjExplicitLod:2671case SpvOpImageSampleProjDrefExplicitLod:2672texop = nir_texop_txl;2673break;26742675case SpvOpImageFetch:2676case SpvOpImageSparseFetch:2677if (sampler_dim == GLSL_SAMPLER_DIM_MS) {2678texop = nir_texop_txf_ms;2679} else {2680texop = nir_texop_txf;2681}2682break;26832684case SpvOpImageGather:2685case SpvOpImageSparseGather:2686case SpvOpImageDrefGather:2687case SpvOpImageSparseDrefGather:2688texop = nir_texop_tg4;2689break;26902691case SpvOpImageQuerySizeLod:2692case SpvOpImageQuerySize:2693texop = nir_texop_txs;2694dest_type = nir_type_int32;2695break;26962697case SpvOpImageQueryLod:2698texop = nir_texop_lod;2699dest_type = nir_type_float32;2700break;27012702case SpvOpImageQueryLevels:2703texop = nir_texop_query_levels;2704dest_type = nir_type_int32;2705break;27062707case SpvOpImageQuerySamples:2708texop = nir_texop_texture_samples;2709dest_type = nir_type_int32;2710break;27112712case SpvOpFragmentFetchAMD:2713texop = nir_texop_fragment_fetch;2714break;27152716case SpvOpFragmentMaskFetchAMD:2717texop = nir_texop_fragment_mask_fetch;2718dest_type = nir_type_uint32;2719break;27202721default:2722vtn_fail_with_opcode("Unhandled opcode", opcode);2723}27242725nir_tex_src srcs[10]; /* 10 should be enough */2726nir_tex_src *p = srcs;27272728p->src = nir_src_for_ssa(&image->dest.ssa);2729p->src_type = nir_tex_src_texture_deref;2730p++;27312732switch (texop) {2733case nir_texop_tex:2734case nir_texop_txb:2735case nir_texop_txl:2736case nir_texop_txd:2737case nir_texop_tg4:2738case nir_texop_lod:2739vtn_fail_if(sampler == NULL,2740"%s requires an image of type OpTypeSampledImage",2741spirv_op_to_string(opcode));2742p->src = nir_src_for_ssa(&sampler->dest.ssa);2743p->src_type = nir_tex_src_sampler_deref;2744p++;2745break;2746case nir_texop_txf:2747case nir_texop_txf_ms:2748case nir_texop_txs:2749case nir_texop_query_levels:2750case nir_texop_texture_samples:2751case nir_texop_samples_identical:2752case nir_texop_fragment_fetch:2753case nir_texop_fragment_mask_fetch:2754/* These don't */2755break;2756case nir_texop_txf_ms_fb:2757vtn_fail("unexpected nir_texop_txf_ms_fb");2758break;2759case nir_texop_txf_ms_mcs:2760vtn_fail("unexpected nir_texop_txf_ms_mcs");2761case nir_texop_tex_prefetch:2762vtn_fail("unexpected nir_texop_tex_prefetch");2763}27642765unsigned idx = 4;27662767struct nir_ssa_def *coord;2768unsigned coord_components;2769switch (opcode) {2770case SpvOpImageSampleImplicitLod:2771case SpvOpImageSparseSampleImplicitLod:2772case SpvOpImageSampleExplicitLod:2773case SpvOpImageSparseSampleExplicitLod:2774case SpvOpImageSampleDrefImplicitLod:2775case SpvOpImageSparseSampleDrefImplicitLod:2776case SpvOpImageSampleDrefExplicitLod:2777case SpvOpImageSparseSampleDrefExplicitLod:2778case SpvOpImageSampleProjImplicitLod:2779case SpvOpImageSampleProjExplicitLod:2780case SpvOpImageSampleProjDrefImplicitLod:2781case SpvOpImageSampleProjDrefExplicitLod:2782case SpvOpImageFetch:2783case SpvOpImageSparseFetch:2784case SpvOpImageGather:2785case SpvOpImageSparseGather:2786case SpvOpImageDrefGather:2787case SpvOpImageSparseDrefGather:2788case SpvOpImageQueryLod:2789case SpvOpFragmentFetchAMD:2790case SpvOpFragmentMaskFetchAMD: {2791/* All these types have the coordinate as their first real argument */2792coord_components = glsl_get_sampler_dim_coordinate_components(sampler_dim);27932794if (is_array && texop != nir_texop_lod)2795coord_components++;27962797struct vtn_ssa_value *coord_val = vtn_ssa_value(b, w[idx++]);2798coord = coord_val->def;2799p->src = nir_src_for_ssa(nir_channels(&b->nb, coord,2800(1 << coord_components) - 1));28012802/* OpenCL allows integer sampling coordinates */2803if (glsl_type_is_integer(coord_val->type) &&2804opcode == SpvOpImageSampleExplicitLod) {2805vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,2806"Unless the Kernel capability is being used, the coordinate parameter "2807"OpImageSampleExplicitLod must be floating point.");28082809p->src = nir_src_for_ssa(2810nir_fadd(&b->nb, nir_i2f32(&b->nb, p->src.ssa),2811nir_imm_float(&b->nb, 0.5)));2812}28132814p->src_type = nir_tex_src_coord;2815p++;2816break;2817}28182819default:2820coord = NULL;2821coord_components = 0;2822break;2823}28242825switch (opcode) {2826case SpvOpImageSampleProjImplicitLod:2827case SpvOpImageSampleProjExplicitLod:2828case SpvOpImageSampleProjDrefImplicitLod:2829case SpvOpImageSampleProjDrefExplicitLod:2830/* These have the projector as the last coordinate component */2831p->src = nir_src_for_ssa(nir_channel(&b->nb, coord, coord_components));2832p->src_type = nir_tex_src_projector;2833p++;2834break;28352836default:2837break;2838}28392840bool is_shadow = false;2841unsigned gather_component = 0;2842switch (opcode) {2843case SpvOpImageSampleDrefImplicitLod:2844case SpvOpImageSparseSampleDrefImplicitLod:2845case SpvOpImageSampleDrefExplicitLod:2846case SpvOpImageSparseSampleDrefExplicitLod:2847case SpvOpImageSampleProjDrefImplicitLod:2848case SpvOpImageSampleProjDrefExplicitLod:2849case SpvOpImageDrefGather:2850case SpvOpImageSparseDrefGather:2851/* These all have an explicit depth value as their next source */2852is_shadow = true;2853(*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_comparator);2854break;28552856case SpvOpImageGather:2857case SpvOpImageSparseGather:2858/* This has a component as its next source */2859gather_component = vtn_constant_uint(b, w[idx++]);2860break;28612862default:2863break;2864}28652866bool is_sparse = false;2867switch (opcode) {2868case SpvOpImageSparseSampleImplicitLod:2869case SpvOpImageSparseSampleExplicitLod:2870case SpvOpImageSparseSampleDrefImplicitLod:2871case SpvOpImageSparseSampleDrefExplicitLod:2872case SpvOpImageSparseFetch:2873case SpvOpImageSparseGather:2874case SpvOpImageSparseDrefGather:2875is_sparse = true;2876break;2877default:2878break;2879}28802881/* For OpImageQuerySizeLod, we always have an LOD */2882if (opcode == SpvOpImageQuerySizeLod)2883(*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);28842885/* For OpFragmentFetchAMD, we always have a multisample index */2886if (opcode == SpvOpFragmentFetchAMD)2887(*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ms_index);28882889/* Now we need to handle some number of optional arguments */2890struct vtn_value *gather_offsets = NULL;2891uint32_t operands = SpvImageOperandsMaskNone;2892if (idx < count) {2893operands = w[idx];28942895if (operands & SpvImageOperandsBiasMask) {2896vtn_assert(texop == nir_texop_tex ||2897texop == nir_texop_tg4);2898if (texop == nir_texop_tex)2899texop = nir_texop_txb;2900uint32_t arg = image_operand_arg(b, w, count, idx,2901SpvImageOperandsBiasMask);2902(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_bias);2903}29042905if (operands & SpvImageOperandsLodMask) {2906vtn_assert(texop == nir_texop_txl || texop == nir_texop_txf ||2907texop == nir_texop_txs || texop == nir_texop_tg4);2908uint32_t arg = image_operand_arg(b, w, count, idx,2909SpvImageOperandsLodMask);2910(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_lod);2911}29122913if (operands & SpvImageOperandsGradMask) {2914vtn_assert(texop == nir_texop_txl);2915texop = nir_texop_txd;2916uint32_t arg = image_operand_arg(b, w, count, idx,2917SpvImageOperandsGradMask);2918(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_ddx);2919(*p++) = vtn_tex_src(b, w[arg + 1], nir_tex_src_ddy);2920}29212922vtn_fail_if(util_bitcount(operands & (SpvImageOperandsConstOffsetsMask |2923SpvImageOperandsOffsetMask |2924SpvImageOperandsConstOffsetMask)) > 1,2925"At most one of the ConstOffset, Offset, and ConstOffsets "2926"image operands can be used on a given instruction.");29272928if (operands & SpvImageOperandsOffsetMask) {2929uint32_t arg = image_operand_arg(b, w, count, idx,2930SpvImageOperandsOffsetMask);2931(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_offset);2932}29332934if (operands & SpvImageOperandsConstOffsetMask) {2935uint32_t arg = image_operand_arg(b, w, count, idx,2936SpvImageOperandsConstOffsetMask);2937(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_offset);2938}29392940if (operands & SpvImageOperandsConstOffsetsMask) {2941vtn_assert(texop == nir_texop_tg4);2942uint32_t arg = image_operand_arg(b, w, count, idx,2943SpvImageOperandsConstOffsetsMask);2944gather_offsets = vtn_value(b, w[arg], vtn_value_type_constant);2945}29462947if (operands & SpvImageOperandsSampleMask) {2948vtn_assert(texop == nir_texop_txf_ms);2949uint32_t arg = image_operand_arg(b, w, count, idx,2950SpvImageOperandsSampleMask);2951texop = nir_texop_txf_ms;2952(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_ms_index);2953}29542955if (operands & SpvImageOperandsMinLodMask) {2956vtn_assert(texop == nir_texop_tex ||2957texop == nir_texop_txb ||2958texop == nir_texop_txd);2959uint32_t arg = image_operand_arg(b, w, count, idx,2960SpvImageOperandsMinLodMask);2961(*p++) = vtn_tex_src(b, w[arg], nir_tex_src_min_lod);2962}2963}29642965struct vtn_type *ret_type = vtn_get_type(b, w[1]);2966struct vtn_type *struct_type = NULL;2967if (is_sparse) {2968vtn_assert(glsl_type_is_struct_or_ifc(ret_type->type));2969struct_type = ret_type;2970ret_type = struct_type->members[1];2971}29722973nir_tex_instr *instr = nir_tex_instr_create(b->shader, p - srcs);2974instr->op = texop;29752976memcpy(instr->src, srcs, instr->num_srcs * sizeof(*instr->src));29772978instr->coord_components = coord_components;2979instr->sampler_dim = sampler_dim;2980instr->is_array = is_array;2981instr->is_shadow = is_shadow;2982instr->is_sparse = is_sparse;2983instr->is_new_style_shadow =2984is_shadow && glsl_get_components(ret_type->type) == 1;2985instr->component = gather_component;29862987/* The Vulkan spec says:2988*2989* "If an instruction loads from or stores to a resource (including2990* atomics and image instructions) and the resource descriptor being2991* accessed is not dynamically uniform, then the operand corresponding2992* to that resource (e.g. the pointer or sampled image operand) must be2993* decorated with NonUniform."2994*2995* It's very careful to specify that the exact operand must be decorated2996* NonUniform. The SPIR-V parser is not expected to chase through long2997* chains to find the NonUniform decoration. It's either right there or we2998* can assume it doesn't exist.2999*/3000enum gl_access_qualifier access = 0;3001vtn_foreach_decoration(b, sampled_val, non_uniform_decoration_cb, &access);30023003if (sampled_val->propagated_non_uniform)3004access |= ACCESS_NON_UNIFORM;30053006if (image && (access & ACCESS_NON_UNIFORM))3007instr->texture_non_uniform = true;30083009if (sampler && (access & ACCESS_NON_UNIFORM))3010instr->sampler_non_uniform = true;30113012/* for non-query ops, get dest_type from SPIR-V return type */3013if (dest_type == nir_type_invalid) {3014/* the return type should match the image type, unless the image type is3015* VOID (CL image), in which case the return type dictates the sampler3016*/3017enum glsl_base_type sampler_base =3018glsl_get_sampler_result_type(image->type);3019enum glsl_base_type ret_base = glsl_get_base_type(ret_type->type);3020vtn_fail_if(sampler_base != ret_base && sampler_base != GLSL_TYPE_VOID,3021"SPIR-V return type mismatches image type. This is only valid "3022"for untyped images (OpenCL).");3023dest_type = nir_get_nir_type_for_glsl_base_type(ret_base);3024dest_type = get_image_type(b, dest_type, operands);3025}30263027instr->dest_type = dest_type;30283029nir_ssa_dest_init(&instr->instr, &instr->dest,3030nir_tex_instr_dest_size(instr), 32, NULL);30313032vtn_assert(glsl_get_vector_elements(ret_type->type) ==3033nir_tex_instr_result_size(instr));30343035if (gather_offsets) {3036vtn_fail_if(gather_offsets->type->base_type != vtn_base_type_array ||3037gather_offsets->type->length != 4,3038"ConstOffsets must be an array of size four of vectors "3039"of two integer components");30403041struct vtn_type *vec_type = gather_offsets->type->array_element;3042vtn_fail_if(vec_type->base_type != vtn_base_type_vector ||3043vec_type->length != 2 ||3044!glsl_type_is_integer(vec_type->type),3045"ConstOffsets must be an array of size four of vectors "3046"of two integer components");30473048unsigned bit_size = glsl_get_bit_size(vec_type->type);3049for (uint32_t i = 0; i < 4; i++) {3050const nir_const_value *cvec =3051gather_offsets->constant->elements[i]->values;3052for (uint32_t j = 0; j < 2; j++) {3053switch (bit_size) {3054case 8: instr->tg4_offsets[i][j] = cvec[j].i8; break;3055case 16: instr->tg4_offsets[i][j] = cvec[j].i16; break;3056case 32: instr->tg4_offsets[i][j] = cvec[j].i32; break;3057case 64: instr->tg4_offsets[i][j] = cvec[j].i64; break;3058default:3059vtn_fail("Unsupported bit size: %u", bit_size);3060}3061}3062}3063}30643065nir_builder_instr_insert(&b->nb, &instr->instr);30663067if (is_sparse) {3068struct vtn_ssa_value *dest = vtn_create_ssa_value(b, struct_type->type);3069unsigned result_size = glsl_get_vector_elements(ret_type->type);3070dest->elems[0]->def = nir_channel(&b->nb, &instr->dest.ssa, result_size);3071dest->elems[1]->def = nir_channels(&b->nb, &instr->dest.ssa,3072BITFIELD_MASK(result_size));3073vtn_push_ssa_value(b, w[2], dest);3074} else {3075vtn_push_nir_ssa(b, w[2], &instr->dest.ssa);3076}3077}30783079static void3080fill_common_atomic_sources(struct vtn_builder *b, SpvOp opcode,3081const uint32_t *w, nir_src *src)3082{3083const struct glsl_type *type = vtn_get_type(b, w[1])->type;3084unsigned bit_size = glsl_get_bit_size(type);30853086switch (opcode) {3087case SpvOpAtomicIIncrement:3088src[0] = nir_src_for_ssa(nir_imm_intN_t(&b->nb, 1, bit_size));3089break;30903091case SpvOpAtomicIDecrement:3092src[0] = nir_src_for_ssa(nir_imm_intN_t(&b->nb, -1, bit_size));3093break;30943095case SpvOpAtomicISub:3096src[0] =3097nir_src_for_ssa(nir_ineg(&b->nb, vtn_get_nir_ssa(b, w[6])));3098break;30993100case SpvOpAtomicCompareExchange:3101case SpvOpAtomicCompareExchangeWeak:3102src[0] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[8]));3103src[1] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[7]));3104break;31053106case SpvOpAtomicExchange:3107case SpvOpAtomicIAdd:3108case SpvOpAtomicSMin:3109case SpvOpAtomicUMin:3110case SpvOpAtomicSMax:3111case SpvOpAtomicUMax:3112case SpvOpAtomicAnd:3113case SpvOpAtomicOr:3114case SpvOpAtomicXor:3115case SpvOpAtomicFAddEXT:3116case SpvOpAtomicFMinEXT:3117case SpvOpAtomicFMaxEXT:3118src[0] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[6]));3119break;31203121default:3122vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode);3123}3124}31253126static nir_ssa_def *3127get_image_coord(struct vtn_builder *b, uint32_t value)3128{3129nir_ssa_def *coord = vtn_get_nir_ssa(b, value);3130/* The image_load_store intrinsics assume a 4-dim coordinate */3131return nir_pad_vec4(&b->nb, coord);3132}31333134static void3135vtn_handle_image(struct vtn_builder *b, SpvOp opcode,3136const uint32_t *w, unsigned count)3137{3138/* Just get this one out of the way */3139if (opcode == SpvOpImageTexelPointer) {3140struct vtn_value *val =3141vtn_push_value(b, w[2], vtn_value_type_image_pointer);3142val->image = ralloc(b, struct vtn_image_pointer);31433144val->image->image = vtn_nir_deref(b, w[3]);3145val->image->coord = get_image_coord(b, w[4]);3146val->image->sample = vtn_get_nir_ssa(b, w[5]);3147val->image->lod = nir_imm_int(&b->nb, 0);3148return;3149}31503151struct vtn_image_pointer image;3152SpvScope scope = SpvScopeInvocation;3153SpvMemorySemanticsMask semantics = 0;3154SpvImageOperandsMask operands = SpvImageOperandsMaskNone;31553156enum gl_access_qualifier access = 0;31573158struct vtn_value *res_val;3159switch (opcode) {3160case SpvOpAtomicExchange:3161case SpvOpAtomicCompareExchange:3162case SpvOpAtomicCompareExchangeWeak:3163case SpvOpAtomicIIncrement:3164case SpvOpAtomicIDecrement:3165case SpvOpAtomicIAdd:3166case SpvOpAtomicISub:3167case SpvOpAtomicLoad:3168case SpvOpAtomicSMin:3169case SpvOpAtomicUMin:3170case SpvOpAtomicSMax:3171case SpvOpAtomicUMax:3172case SpvOpAtomicAnd:3173case SpvOpAtomicOr:3174case SpvOpAtomicXor:3175case SpvOpAtomicFAddEXT:3176case SpvOpAtomicFMinEXT:3177case SpvOpAtomicFMaxEXT:3178res_val = vtn_value(b, w[3], vtn_value_type_image_pointer);3179image = *res_val->image;3180scope = vtn_constant_uint(b, w[4]);3181semantics = vtn_constant_uint(b, w[5]);3182access |= ACCESS_COHERENT;3183break;31843185case SpvOpAtomicStore:3186res_val = vtn_value(b, w[1], vtn_value_type_image_pointer);3187image = *res_val->image;3188scope = vtn_constant_uint(b, w[2]);3189semantics = vtn_constant_uint(b, w[3]);3190access |= ACCESS_COHERENT;3191break;31923193case SpvOpImageQuerySizeLod:3194res_val = vtn_untyped_value(b, w[3]);3195image.image = vtn_get_image(b, w[3], &access);3196image.coord = NULL;3197image.sample = NULL;3198image.lod = vtn_ssa_value(b, w[4])->def;3199break;32003201case SpvOpImageQuerySize:3202case SpvOpImageQuerySamples:3203res_val = vtn_untyped_value(b, w[3]);3204image.image = vtn_get_image(b, w[3], &access);3205image.coord = NULL;3206image.sample = NULL;3207image.lod = NULL;3208break;32093210case SpvOpImageQueryFormat:3211case SpvOpImageQueryOrder:3212res_val = vtn_untyped_value(b, w[3]);3213image.image = vtn_get_image(b, w[3], &access);3214image.coord = NULL;3215image.sample = NULL;3216image.lod = NULL;3217break;32183219case SpvOpImageRead:3220case SpvOpImageSparseRead: {3221res_val = vtn_untyped_value(b, w[3]);3222image.image = vtn_get_image(b, w[3], &access);3223image.coord = get_image_coord(b, w[4]);32243225operands = count > 5 ? w[5] : SpvImageOperandsMaskNone;32263227if (operands & SpvImageOperandsSampleMask) {3228uint32_t arg = image_operand_arg(b, w, count, 5,3229SpvImageOperandsSampleMask);3230image.sample = vtn_get_nir_ssa(b, w[arg]);3231} else {3232image.sample = nir_ssa_undef(&b->nb, 1, 32);3233}32343235if (operands & SpvImageOperandsMakeTexelVisibleMask) {3236vtn_fail_if((operands & SpvImageOperandsNonPrivateTexelMask) == 0,3237"MakeTexelVisible requires NonPrivateTexel to also be set.");3238uint32_t arg = image_operand_arg(b, w, count, 5,3239SpvImageOperandsMakeTexelVisibleMask);3240semantics = SpvMemorySemanticsMakeVisibleMask;3241scope = vtn_constant_uint(b, w[arg]);3242}32433244if (operands & SpvImageOperandsLodMask) {3245uint32_t arg = image_operand_arg(b, w, count, 5,3246SpvImageOperandsLodMask);3247image.lod = vtn_get_nir_ssa(b, w[arg]);3248} else {3249image.lod = nir_imm_int(&b->nb, 0);3250}32513252if (operands & SpvImageOperandsVolatileTexelMask)3253access |= ACCESS_VOLATILE;32543255break;3256}32573258case SpvOpImageWrite: {3259res_val = vtn_untyped_value(b, w[1]);3260image.image = vtn_get_image(b, w[1], &access);3261image.coord = get_image_coord(b, w[2]);32623263/* texel = w[3] */32643265operands = count > 4 ? w[4] : SpvImageOperandsMaskNone;32663267if (operands & SpvImageOperandsSampleMask) {3268uint32_t arg = image_operand_arg(b, w, count, 4,3269SpvImageOperandsSampleMask);3270image.sample = vtn_get_nir_ssa(b, w[arg]);3271} else {3272image.sample = nir_ssa_undef(&b->nb, 1, 32);3273}32743275if (operands & SpvImageOperandsMakeTexelAvailableMask) {3276vtn_fail_if((operands & SpvImageOperandsNonPrivateTexelMask) == 0,3277"MakeTexelAvailable requires NonPrivateTexel to also be set.");3278uint32_t arg = image_operand_arg(b, w, count, 4,3279SpvImageOperandsMakeTexelAvailableMask);3280semantics = SpvMemorySemanticsMakeAvailableMask;3281scope = vtn_constant_uint(b, w[arg]);3282}32833284if (operands & SpvImageOperandsLodMask) {3285uint32_t arg = image_operand_arg(b, w, count, 4,3286SpvImageOperandsLodMask);3287image.lod = vtn_get_nir_ssa(b, w[arg]);3288} else {3289image.lod = nir_imm_int(&b->nb, 0);3290}32913292if (operands & SpvImageOperandsVolatileTexelMask)3293access |= ACCESS_VOLATILE;32943295break;3296}32973298default:3299vtn_fail_with_opcode("Invalid image opcode", opcode);3300}33013302if (semantics & SpvMemorySemanticsVolatileMask)3303access |= ACCESS_VOLATILE;33043305nir_intrinsic_op op;3306switch (opcode) {3307#define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break;3308OP(ImageQuerySize, size)3309OP(ImageQuerySizeLod, size)3310OP(ImageRead, load)3311OP(ImageSparseRead, sparse_load)3312OP(ImageWrite, store)3313OP(AtomicLoad, load)3314OP(AtomicStore, store)3315OP(AtomicExchange, atomic_exchange)3316OP(AtomicCompareExchange, atomic_comp_swap)3317OP(AtomicCompareExchangeWeak, atomic_comp_swap)3318OP(AtomicIIncrement, atomic_add)3319OP(AtomicIDecrement, atomic_add)3320OP(AtomicIAdd, atomic_add)3321OP(AtomicISub, atomic_add)3322OP(AtomicSMin, atomic_imin)3323OP(AtomicUMin, atomic_umin)3324OP(AtomicSMax, atomic_imax)3325OP(AtomicUMax, atomic_umax)3326OP(AtomicAnd, atomic_and)3327OP(AtomicOr, atomic_or)3328OP(AtomicXor, atomic_xor)3329OP(AtomicFAddEXT, atomic_fadd)3330OP(AtomicFMinEXT, atomic_fmin)3331OP(AtomicFMaxEXT, atomic_fmax)3332OP(ImageQueryFormat, format)3333OP(ImageQueryOrder, order)3334OP(ImageQuerySamples, samples)3335#undef OP3336default:3337vtn_fail_with_opcode("Invalid image opcode", opcode);3338}33393340nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);33413342intrin->src[0] = nir_src_for_ssa(&image.image->dest.ssa);33433344switch (opcode) {3345case SpvOpImageQuerySamples:3346case SpvOpImageQuerySize:3347case SpvOpImageQuerySizeLod:3348case SpvOpImageQueryFormat:3349case SpvOpImageQueryOrder:3350break;3351default:3352/* The image coordinate is always 4 components but we may not have that3353* many. Swizzle to compensate.3354*/3355intrin->src[1] = nir_src_for_ssa(nir_pad_vec4(&b->nb, image.coord));3356intrin->src[2] = nir_src_for_ssa(image.sample);3357break;3358}33593360/* The Vulkan spec says:3361*3362* "If an instruction loads from or stores to a resource (including3363* atomics and image instructions) and the resource descriptor being3364* accessed is not dynamically uniform, then the operand corresponding3365* to that resource (e.g. the pointer or sampled image operand) must be3366* decorated with NonUniform."3367*3368* It's very careful to specify that the exact operand must be decorated3369* NonUniform. The SPIR-V parser is not expected to chase through long3370* chains to find the NonUniform decoration. It's either right there or we3371* can assume it doesn't exist.3372*/3373vtn_foreach_decoration(b, res_val, non_uniform_decoration_cb, &access);3374nir_intrinsic_set_access(intrin, access);33753376switch (opcode) {3377case SpvOpImageQuerySamples:3378case SpvOpImageQueryFormat:3379case SpvOpImageQueryOrder:3380/* No additional sources */3381break;3382case SpvOpImageQuerySize:3383intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0));3384break;3385case SpvOpImageQuerySizeLod:3386intrin->src[1] = nir_src_for_ssa(image.lod);3387break;3388case SpvOpAtomicLoad:3389case SpvOpImageRead:3390case SpvOpImageSparseRead:3391/* Only OpImageRead can support a lod parameter if3392* SPV_AMD_shader_image_load_store_lod is used but the current NIR3393* intrinsics definition for atomics requires us to set it for3394* OpAtomicLoad.3395*/3396intrin->src[3] = nir_src_for_ssa(image.lod);3397break;3398case SpvOpAtomicStore:3399case SpvOpImageWrite: {3400const uint32_t value_id = opcode == SpvOpAtomicStore ? w[4] : w[3];3401struct vtn_ssa_value *value = vtn_ssa_value(b, value_id);3402/* nir_intrinsic_image_deref_store always takes a vec4 value */3403assert(op == nir_intrinsic_image_deref_store);3404intrin->num_components = 4;3405intrin->src[3] = nir_src_for_ssa(nir_pad_vec4(&b->nb, value->def));3406/* Only OpImageWrite can support a lod parameter if3407* SPV_AMD_shader_image_load_store_lod is used but the current NIR3408* intrinsics definition for atomics requires us to set it for3409* OpAtomicStore.3410*/3411intrin->src[4] = nir_src_for_ssa(image.lod);34123413if (opcode == SpvOpImageWrite) {3414nir_alu_type src_type =3415get_image_type(b, nir_get_nir_type_for_glsl_type(value->type), operands);3416nir_intrinsic_set_src_type(intrin, src_type);3417}3418break;3419}34203421case SpvOpAtomicCompareExchange:3422case SpvOpAtomicCompareExchangeWeak:3423case SpvOpAtomicIIncrement:3424case SpvOpAtomicIDecrement:3425case SpvOpAtomicExchange:3426case SpvOpAtomicIAdd:3427case SpvOpAtomicISub:3428case SpvOpAtomicSMin:3429case SpvOpAtomicUMin:3430case SpvOpAtomicSMax:3431case SpvOpAtomicUMax:3432case SpvOpAtomicAnd:3433case SpvOpAtomicOr:3434case SpvOpAtomicXor:3435case SpvOpAtomicFAddEXT:3436case SpvOpAtomicFMinEXT:3437case SpvOpAtomicFMaxEXT:3438fill_common_atomic_sources(b, opcode, w, &intrin->src[3]);3439break;34403441default:3442vtn_fail_with_opcode("Invalid image opcode", opcode);3443}34443445/* Image operations implicitly have the Image storage memory semantics. */3446semantics |= SpvMemorySemanticsImageMemoryMask;34473448SpvMemorySemanticsMask before_semantics;3449SpvMemorySemanticsMask after_semantics;3450vtn_split_barrier_semantics(b, semantics, &before_semantics, &after_semantics);34513452if (before_semantics)3453vtn_emit_memory_barrier(b, scope, before_semantics);34543455if (opcode != SpvOpImageWrite && opcode != SpvOpAtomicStore) {3456struct vtn_type *type = vtn_get_type(b, w[1]);3457struct vtn_type *struct_type = NULL;3458if (opcode == SpvOpImageSparseRead) {3459vtn_assert(glsl_type_is_struct_or_ifc(type->type));3460struct_type = type;3461type = struct_type->members[1];3462}34633464unsigned dest_components = glsl_get_vector_elements(type->type);3465if (opcode == SpvOpImageSparseRead)3466dest_components++;34673468if (nir_intrinsic_infos[op].dest_components == 0)3469intrin->num_components = dest_components;34703471nir_ssa_dest_init(&intrin->instr, &intrin->dest,3472nir_intrinsic_dest_components(intrin),3473glsl_get_bit_size(type->type), NULL);34743475nir_builder_instr_insert(&b->nb, &intrin->instr);34763477nir_ssa_def *result = &intrin->dest.ssa;3478if (nir_intrinsic_dest_components(intrin) != dest_components)3479result = nir_channels(&b->nb, result, (1 << dest_components) - 1);34803481if (opcode == SpvOpImageSparseRead) {3482struct vtn_ssa_value *dest = vtn_create_ssa_value(b, struct_type->type);3483unsigned res_type_size = glsl_get_vector_elements(type->type);3484dest->elems[0]->def = nir_channel(&b->nb, result, res_type_size);3485if (intrin->dest.ssa.bit_size != 32)3486dest->elems[0]->def = nir_u2u32(&b->nb, dest->elems[0]->def);3487dest->elems[1]->def = nir_channels(&b->nb, result,3488BITFIELD_MASK(res_type_size));3489vtn_push_ssa_value(b, w[2], dest);3490} else {3491vtn_push_nir_ssa(b, w[2], result);3492}34933494if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead) {3495nir_alu_type dest_type =3496get_image_type(b, nir_get_nir_type_for_glsl_type(type->type), operands);3497nir_intrinsic_set_dest_type(intrin, dest_type);3498}3499} else {3500nir_builder_instr_insert(&b->nb, &intrin->instr);3501}35023503if (after_semantics)3504vtn_emit_memory_barrier(b, scope, after_semantics);3505}35063507static nir_intrinsic_op3508get_uniform_nir_atomic_op(struct vtn_builder *b, SpvOp opcode)3509{3510switch (opcode) {3511#define OP(S, N) case SpvOp##S: return nir_intrinsic_atomic_counter_ ##N;3512OP(AtomicLoad, read_deref)3513OP(AtomicExchange, exchange)3514OP(AtomicCompareExchange, comp_swap)3515OP(AtomicCompareExchangeWeak, comp_swap)3516OP(AtomicIIncrement, inc_deref)3517OP(AtomicIDecrement, post_dec_deref)3518OP(AtomicIAdd, add_deref)3519OP(AtomicISub, add_deref)3520OP(AtomicUMin, min_deref)3521OP(AtomicUMax, max_deref)3522OP(AtomicAnd, and_deref)3523OP(AtomicOr, or_deref)3524OP(AtomicXor, xor_deref)3525#undef OP3526default:3527/* We left the following out: AtomicStore, AtomicSMin and3528* AtomicSmax. Right now there are not nir intrinsics for them. At this3529* moment Atomic Counter support is needed for ARB_spirv support, so is3530* only need to support GLSL Atomic Counters that are uints and don't3531* allow direct storage.3532*/3533vtn_fail("Invalid uniform atomic");3534}3535}35363537static nir_intrinsic_op3538get_deref_nir_atomic_op(struct vtn_builder *b, SpvOp opcode)3539{3540switch (opcode) {3541case SpvOpAtomicLoad: return nir_intrinsic_load_deref;3542case SpvOpAtomicStore: return nir_intrinsic_store_deref;3543#define OP(S, N) case SpvOp##S: return nir_intrinsic_deref_##N;3544OP(AtomicExchange, atomic_exchange)3545OP(AtomicCompareExchange, atomic_comp_swap)3546OP(AtomicCompareExchangeWeak, atomic_comp_swap)3547OP(AtomicIIncrement, atomic_add)3548OP(AtomicIDecrement, atomic_add)3549OP(AtomicIAdd, atomic_add)3550OP(AtomicISub, atomic_add)3551OP(AtomicSMin, atomic_imin)3552OP(AtomicUMin, atomic_umin)3553OP(AtomicSMax, atomic_imax)3554OP(AtomicUMax, atomic_umax)3555OP(AtomicAnd, atomic_and)3556OP(AtomicOr, atomic_or)3557OP(AtomicXor, atomic_xor)3558OP(AtomicFAddEXT, atomic_fadd)3559OP(AtomicFMinEXT, atomic_fmin)3560OP(AtomicFMaxEXT, atomic_fmax)3561#undef OP3562default:3563vtn_fail_with_opcode("Invalid shared atomic", opcode);3564}3565}35663567/*3568* Handles shared atomics, ssbo atomics and atomic counters.3569*/3570static void3571vtn_handle_atomics(struct vtn_builder *b, SpvOp opcode,3572const uint32_t *w, UNUSED unsigned count)3573{3574struct vtn_pointer *ptr;3575nir_intrinsic_instr *atomic;35763577SpvScope scope = SpvScopeInvocation;3578SpvMemorySemanticsMask semantics = 0;3579enum gl_access_qualifier access = 0;35803581switch (opcode) {3582case SpvOpAtomicLoad:3583case SpvOpAtomicExchange:3584case SpvOpAtomicCompareExchange:3585case SpvOpAtomicCompareExchangeWeak:3586case SpvOpAtomicIIncrement:3587case SpvOpAtomicIDecrement:3588case SpvOpAtomicIAdd:3589case SpvOpAtomicISub:3590case SpvOpAtomicSMin:3591case SpvOpAtomicUMin:3592case SpvOpAtomicSMax:3593case SpvOpAtomicUMax:3594case SpvOpAtomicAnd:3595case SpvOpAtomicOr:3596case SpvOpAtomicXor:3597case SpvOpAtomicFAddEXT:3598case SpvOpAtomicFMinEXT:3599case SpvOpAtomicFMaxEXT:3600ptr = vtn_value(b, w[3], vtn_value_type_pointer)->pointer;3601scope = vtn_constant_uint(b, w[4]);3602semantics = vtn_constant_uint(b, w[5]);3603break;36043605case SpvOpAtomicStore:3606ptr = vtn_value(b, w[1], vtn_value_type_pointer)->pointer;3607scope = vtn_constant_uint(b, w[2]);3608semantics = vtn_constant_uint(b, w[3]);3609break;36103611default:3612vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode);3613}36143615if (semantics & SpvMemorySemanticsVolatileMask)3616access |= ACCESS_VOLATILE;36173618/* uniform as "atomic counter uniform" */3619if (ptr->mode == vtn_variable_mode_atomic_counter) {3620nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr);3621nir_intrinsic_op op = get_uniform_nir_atomic_op(b, opcode);3622atomic = nir_intrinsic_instr_create(b->nb.shader, op);3623atomic->src[0] = nir_src_for_ssa(&deref->dest.ssa);36243625/* SSBO needs to initialize index/offset. In this case we don't need to,3626* as that info is already stored on the ptr->var->var nir_variable (see3627* vtn_create_variable)3628*/36293630switch (opcode) {3631case SpvOpAtomicLoad:3632case SpvOpAtomicExchange:3633case SpvOpAtomicCompareExchange:3634case SpvOpAtomicCompareExchangeWeak:3635case SpvOpAtomicIIncrement:3636case SpvOpAtomicIDecrement:3637case SpvOpAtomicIAdd:3638case SpvOpAtomicISub:3639case SpvOpAtomicSMin:3640case SpvOpAtomicUMin:3641case SpvOpAtomicSMax:3642case SpvOpAtomicUMax:3643case SpvOpAtomicAnd:3644case SpvOpAtomicOr:3645case SpvOpAtomicXor:3646/* Nothing: we don't need to call fill_common_atomic_sources here, as3647* atomic counter uniforms doesn't have sources3648*/3649break;36503651default:3652unreachable("Invalid SPIR-V atomic");36533654}3655} else {3656nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr);3657const struct glsl_type *deref_type = deref->type;3658nir_intrinsic_op op = get_deref_nir_atomic_op(b, opcode);3659atomic = nir_intrinsic_instr_create(b->nb.shader, op);3660atomic->src[0] = nir_src_for_ssa(&deref->dest.ssa);36613662if (ptr->mode != vtn_variable_mode_workgroup)3663access |= ACCESS_COHERENT;36643665nir_intrinsic_set_access(atomic, access);36663667switch (opcode) {3668case SpvOpAtomicLoad:3669atomic->num_components = glsl_get_vector_elements(deref_type);3670break;36713672case SpvOpAtomicStore:3673atomic->num_components = glsl_get_vector_elements(deref_type);3674nir_intrinsic_set_write_mask(atomic, (1 << atomic->num_components) - 1);3675atomic->src[1] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[4]));3676break;36773678case SpvOpAtomicExchange:3679case SpvOpAtomicCompareExchange:3680case SpvOpAtomicCompareExchangeWeak:3681case SpvOpAtomicIIncrement:3682case SpvOpAtomicIDecrement:3683case SpvOpAtomicIAdd:3684case SpvOpAtomicISub:3685case SpvOpAtomicSMin:3686case SpvOpAtomicUMin:3687case SpvOpAtomicSMax:3688case SpvOpAtomicUMax:3689case SpvOpAtomicAnd:3690case SpvOpAtomicOr:3691case SpvOpAtomicXor:3692case SpvOpAtomicFAddEXT:3693case SpvOpAtomicFMinEXT:3694case SpvOpAtomicFMaxEXT:3695fill_common_atomic_sources(b, opcode, w, &atomic->src[1]);3696break;36973698default:3699vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode);3700}3701}37023703/* Atomic ordering operations will implicitly apply to the atomic operation3704* storage class, so include that too.3705*/3706semantics |= vtn_mode_to_memory_semantics(ptr->mode);37073708SpvMemorySemanticsMask before_semantics;3709SpvMemorySemanticsMask after_semantics;3710vtn_split_barrier_semantics(b, semantics, &before_semantics, &after_semantics);37113712if (before_semantics)3713vtn_emit_memory_barrier(b, scope, before_semantics);37143715if (opcode != SpvOpAtomicStore) {3716struct vtn_type *type = vtn_get_type(b, w[1]);37173718nir_ssa_dest_init(&atomic->instr, &atomic->dest,3719glsl_get_vector_elements(type->type),3720glsl_get_bit_size(type->type), NULL);37213722vtn_push_nir_ssa(b, w[2], &atomic->dest.ssa);3723}37243725nir_builder_instr_insert(&b->nb, &atomic->instr);37263727if (after_semantics)3728vtn_emit_memory_barrier(b, scope, after_semantics);3729}37303731static nir_alu_instr *3732create_vec(struct vtn_builder *b, unsigned num_components, unsigned bit_size)3733{3734nir_op op = nir_op_vec(num_components);3735nir_alu_instr *vec = nir_alu_instr_create(b->shader, op);3736nir_ssa_dest_init(&vec->instr, &vec->dest.dest, num_components,3737bit_size, NULL);3738vec->dest.write_mask = (1 << num_components) - 1;37393740return vec;3741}37423743struct vtn_ssa_value *3744vtn_ssa_transpose(struct vtn_builder *b, struct vtn_ssa_value *src)3745{3746if (src->transposed)3747return src->transposed;37483749struct vtn_ssa_value *dest =3750vtn_create_ssa_value(b, glsl_transposed_type(src->type));37513752for (unsigned i = 0; i < glsl_get_matrix_columns(dest->type); i++) {3753nir_alu_instr *vec = create_vec(b, glsl_get_matrix_columns(src->type),3754glsl_get_bit_size(src->type));3755if (glsl_type_is_vector_or_scalar(src->type)) {3756vec->src[0].src = nir_src_for_ssa(src->def);3757vec->src[0].swizzle[0] = i;3758} else {3759for (unsigned j = 0; j < glsl_get_matrix_columns(src->type); j++) {3760vec->src[j].src = nir_src_for_ssa(src->elems[j]->def);3761vec->src[j].swizzle[0] = i;3762}3763}3764nir_builder_instr_insert(&b->nb, &vec->instr);3765dest->elems[i]->def = &vec->dest.dest.ssa;3766}37673768dest->transposed = src;37693770return dest;3771}37723773static nir_ssa_def *3774vtn_vector_shuffle(struct vtn_builder *b, unsigned num_components,3775nir_ssa_def *src0, nir_ssa_def *src1,3776const uint32_t *indices)3777{3778nir_alu_instr *vec = create_vec(b, num_components, src0->bit_size);37793780for (unsigned i = 0; i < num_components; i++) {3781uint32_t index = indices[i];3782if (index == 0xffffffff) {3783vec->src[i].src =3784nir_src_for_ssa(nir_ssa_undef(&b->nb, 1, src0->bit_size));3785} else if (index < src0->num_components) {3786vec->src[i].src = nir_src_for_ssa(src0);3787vec->src[i].swizzle[0] = index;3788} else {3789vec->src[i].src = nir_src_for_ssa(src1);3790vec->src[i].swizzle[0] = index - src0->num_components;3791}3792}37933794nir_builder_instr_insert(&b->nb, &vec->instr);37953796return &vec->dest.dest.ssa;3797}37983799/*3800* Concatentates a number of vectors/scalars together to produce a vector3801*/3802static nir_ssa_def *3803vtn_vector_construct(struct vtn_builder *b, unsigned num_components,3804unsigned num_srcs, nir_ssa_def **srcs)3805{3806nir_alu_instr *vec = create_vec(b, num_components, srcs[0]->bit_size);38073808/* From the SPIR-V 1.1 spec for OpCompositeConstruct:3809*3810* "When constructing a vector, there must be at least two Constituent3811* operands."3812*/3813vtn_assert(num_srcs >= 2);38143815unsigned dest_idx = 0;3816for (unsigned i = 0; i < num_srcs; i++) {3817nir_ssa_def *src = srcs[i];3818vtn_assert(dest_idx + src->num_components <= num_components);3819for (unsigned j = 0; j < src->num_components; j++) {3820vec->src[dest_idx].src = nir_src_for_ssa(src);3821vec->src[dest_idx].swizzle[0] = j;3822dest_idx++;3823}3824}38253826/* From the SPIR-V 1.1 spec for OpCompositeConstruct:3827*3828* "When constructing a vector, the total number of components in all3829* the operands must equal the number of components in Result Type."3830*/3831vtn_assert(dest_idx == num_components);38323833nir_builder_instr_insert(&b->nb, &vec->instr);38343835return &vec->dest.dest.ssa;3836}38373838static struct vtn_ssa_value *3839vtn_composite_copy(void *mem_ctx, struct vtn_ssa_value *src)3840{3841struct vtn_ssa_value *dest = rzalloc(mem_ctx, struct vtn_ssa_value);3842dest->type = src->type;38433844if (glsl_type_is_vector_or_scalar(src->type)) {3845dest->def = src->def;3846} else {3847unsigned elems = glsl_get_length(src->type);38483849dest->elems = ralloc_array(mem_ctx, struct vtn_ssa_value *, elems);3850for (unsigned i = 0; i < elems; i++)3851dest->elems[i] = vtn_composite_copy(mem_ctx, src->elems[i]);3852}38533854return dest;3855}38563857static struct vtn_ssa_value *3858vtn_composite_insert(struct vtn_builder *b, struct vtn_ssa_value *src,3859struct vtn_ssa_value *insert, const uint32_t *indices,3860unsigned num_indices)3861{3862struct vtn_ssa_value *dest = vtn_composite_copy(b, src);38633864struct vtn_ssa_value *cur = dest;3865unsigned i;3866for (i = 0; i < num_indices - 1; i++) {3867/* If we got a vector here, that means the next index will be trying to3868* dereference a scalar.3869*/3870vtn_fail_if(glsl_type_is_vector_or_scalar(cur->type),3871"OpCompositeInsert has too many indices.");3872vtn_fail_if(indices[i] >= glsl_get_length(cur->type),3873"All indices in an OpCompositeInsert must be in-bounds");3874cur = cur->elems[indices[i]];3875}38763877if (glsl_type_is_vector_or_scalar(cur->type)) {3878vtn_fail_if(indices[i] >= glsl_get_vector_elements(cur->type),3879"All indices in an OpCompositeInsert must be in-bounds");38803881/* According to the SPIR-V spec, OpCompositeInsert may work down to3882* the component granularity. In that case, the last index will be3883* the index to insert the scalar into the vector.3884*/38853886cur->def = nir_vector_insert_imm(&b->nb, cur->def, insert->def, indices[i]);3887} else {3888vtn_fail_if(indices[i] >= glsl_get_length(cur->type),3889"All indices in an OpCompositeInsert must be in-bounds");3890cur->elems[indices[i]] = insert;3891}38923893return dest;3894}38953896static struct vtn_ssa_value *3897vtn_composite_extract(struct vtn_builder *b, struct vtn_ssa_value *src,3898const uint32_t *indices, unsigned num_indices)3899{3900struct vtn_ssa_value *cur = src;3901for (unsigned i = 0; i < num_indices; i++) {3902if (glsl_type_is_vector_or_scalar(cur->type)) {3903vtn_assert(i == num_indices - 1);3904vtn_fail_if(indices[i] >= glsl_get_vector_elements(cur->type),3905"All indices in an OpCompositeExtract must be in-bounds");39063907/* According to the SPIR-V spec, OpCompositeExtract may work down to3908* the component granularity. The last index will be the index of the3909* vector to extract.3910*/39113912const struct glsl_type *scalar_type =3913glsl_scalar_type(glsl_get_base_type(cur->type));3914struct vtn_ssa_value *ret = vtn_create_ssa_value(b, scalar_type);3915ret->def = nir_channel(&b->nb, cur->def, indices[i]);3916return ret;3917} else {3918vtn_fail_if(indices[i] >= glsl_get_length(cur->type),3919"All indices in an OpCompositeExtract must be in-bounds");3920cur = cur->elems[indices[i]];3921}3922}39233924return cur;3925}39263927static void3928vtn_handle_composite(struct vtn_builder *b, SpvOp opcode,3929const uint32_t *w, unsigned count)3930{3931struct vtn_type *type = vtn_get_type(b, w[1]);3932struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, type->type);39333934switch (opcode) {3935case SpvOpVectorExtractDynamic:3936ssa->def = nir_vector_extract(&b->nb, vtn_get_nir_ssa(b, w[3]),3937vtn_get_nir_ssa(b, w[4]));3938break;39393940case SpvOpVectorInsertDynamic:3941ssa->def = nir_vector_insert(&b->nb, vtn_get_nir_ssa(b, w[3]),3942vtn_get_nir_ssa(b, w[4]),3943vtn_get_nir_ssa(b, w[5]));3944break;39453946case SpvOpVectorShuffle:3947ssa->def = vtn_vector_shuffle(b, glsl_get_vector_elements(type->type),3948vtn_get_nir_ssa(b, w[3]),3949vtn_get_nir_ssa(b, w[4]),3950w + 5);3951break;39523953case SpvOpCompositeConstruct: {3954unsigned elems = count - 3;3955assume(elems >= 1);3956if (glsl_type_is_vector_or_scalar(type->type)) {3957nir_ssa_def *srcs[NIR_MAX_VEC_COMPONENTS];3958for (unsigned i = 0; i < elems; i++)3959srcs[i] = vtn_get_nir_ssa(b, w[3 + i]);3960ssa->def =3961vtn_vector_construct(b, glsl_get_vector_elements(type->type),3962elems, srcs);3963} else {3964ssa->elems = ralloc_array(b, struct vtn_ssa_value *, elems);3965for (unsigned i = 0; i < elems; i++)3966ssa->elems[i] = vtn_ssa_value(b, w[3 + i]);3967}3968break;3969}3970case SpvOpCompositeExtract:3971ssa = vtn_composite_extract(b, vtn_ssa_value(b, w[3]),3972w + 4, count - 4);3973break;39743975case SpvOpCompositeInsert:3976ssa = vtn_composite_insert(b, vtn_ssa_value(b, w[4]),3977vtn_ssa_value(b, w[3]),3978w + 5, count - 5);3979break;39803981case SpvOpCopyLogical:3982ssa = vtn_composite_copy(b, vtn_ssa_value(b, w[3]));3983break;3984case SpvOpCopyObject:3985vtn_copy_value(b, w[3], w[2]);3986return;39873988default:3989vtn_fail_with_opcode("unknown composite operation", opcode);3990}39913992vtn_push_ssa_value(b, w[2], ssa);3993}39943995void3996vtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope,3997SpvMemorySemanticsMask semantics)3998{3999if (b->shader->options->use_scoped_barrier) {4000vtn_emit_scoped_memory_barrier(b, scope, semantics);4001return;4002}40034004static const SpvMemorySemanticsMask all_memory_semantics =4005SpvMemorySemanticsUniformMemoryMask |4006SpvMemorySemanticsWorkgroupMemoryMask |4007SpvMemorySemanticsAtomicCounterMemoryMask |4008SpvMemorySemanticsImageMemoryMask |4009SpvMemorySemanticsOutputMemoryMask;40104011/* If we're not actually doing a memory barrier, bail */4012if (!(semantics & all_memory_semantics))4013return;40144015/* GL and Vulkan don't have these */4016vtn_assert(scope != SpvScopeCrossDevice);40174018if (scope == SpvScopeSubgroup)4019return; /* Nothing to do here */40204021if (scope == SpvScopeWorkgroup) {4022nir_group_memory_barrier(&b->nb);4023return;4024}40254026/* There's only two scopes thing left */4027vtn_assert(scope == SpvScopeInvocation || scope == SpvScopeDevice);40284029/* Map the GLSL memoryBarrier() construct and any barriers with more than one4030* semantic to the corresponding NIR one.4031*/4032if (util_bitcount(semantics & all_memory_semantics) > 1) {4033nir_memory_barrier(&b->nb);4034if (semantics & SpvMemorySemanticsOutputMemoryMask) {4035/* GLSL memoryBarrier() (and the corresponding NIR one) doesn't include4036* TCS outputs, so we have to emit it's own intrinsic for that. We4037* then need to emit another memory_barrier to prevent moving4038* non-output operations to before the tcs_patch barrier.4039*/4040nir_memory_barrier_tcs_patch(&b->nb);4041nir_memory_barrier(&b->nb);4042}4043return;4044}40454046/* Issue a more specific barrier */4047switch (semantics & all_memory_semantics) {4048case SpvMemorySemanticsUniformMemoryMask:4049nir_memory_barrier_buffer(&b->nb);4050break;4051case SpvMemorySemanticsWorkgroupMemoryMask:4052nir_memory_barrier_shared(&b->nb);4053break;4054case SpvMemorySemanticsAtomicCounterMemoryMask:4055nir_memory_barrier_atomic_counter(&b->nb);4056break;4057case SpvMemorySemanticsImageMemoryMask:4058nir_memory_barrier_image(&b->nb);4059break;4060case SpvMemorySemanticsOutputMemoryMask:4061if (b->nb.shader->info.stage == MESA_SHADER_TESS_CTRL)4062nir_memory_barrier_tcs_patch(&b->nb);4063break;4064default:4065break;4066}4067}40684069static void4070vtn_handle_barrier(struct vtn_builder *b, SpvOp opcode,4071const uint32_t *w, UNUSED unsigned count)4072{4073switch (opcode) {4074case SpvOpEmitVertex:4075case SpvOpEmitStreamVertex:4076case SpvOpEndPrimitive:4077case SpvOpEndStreamPrimitive: {4078unsigned stream = 0;4079if (opcode == SpvOpEmitStreamVertex || opcode == SpvOpEndStreamPrimitive)4080stream = vtn_constant_uint(b, w[1]);40814082switch (opcode) {4083case SpvOpEmitStreamVertex:4084case SpvOpEmitVertex:4085nir_emit_vertex(&b->nb, stream);4086break;4087case SpvOpEndPrimitive:4088case SpvOpEndStreamPrimitive:4089nir_end_primitive(&b->nb, stream);4090break;4091default:4092unreachable("Invalid opcode");4093}4094break;4095}40964097case SpvOpMemoryBarrier: {4098SpvScope scope = vtn_constant_uint(b, w[1]);4099SpvMemorySemanticsMask semantics = vtn_constant_uint(b, w[2]);4100vtn_emit_memory_barrier(b, scope, semantics);4101return;4102}41034104case SpvOpControlBarrier: {4105SpvScope execution_scope = vtn_constant_uint(b, w[1]);4106SpvScope memory_scope = vtn_constant_uint(b, w[2]);4107SpvMemorySemanticsMask memory_semantics = vtn_constant_uint(b, w[3]);41084109/* GLSLang, prior to commit 8297936dd6eb3, emitted OpControlBarrier with4110* memory semantics of None for GLSL barrier().4111* And before that, prior to c3f1cdfa, emitted the OpControlBarrier with4112* Device instead of Workgroup for execution scope.4113*/4114if (b->wa_glslang_cs_barrier &&4115b->nb.shader->info.stage == MESA_SHADER_COMPUTE &&4116(execution_scope == SpvScopeWorkgroup ||4117execution_scope == SpvScopeDevice) &&4118memory_semantics == SpvMemorySemanticsMaskNone) {4119execution_scope = SpvScopeWorkgroup;4120memory_scope = SpvScopeWorkgroup;4121memory_semantics = SpvMemorySemanticsAcquireReleaseMask |4122SpvMemorySemanticsWorkgroupMemoryMask;4123}41244125/* From the SPIR-V spec:4126*4127* "When used with the TessellationControl execution model, it also4128* implicitly synchronizes the Output Storage Class: Writes to Output4129* variables performed by any invocation executed prior to a4130* OpControlBarrier will be visible to any other invocation after4131* return from that OpControlBarrier."4132*/4133if (b->nb.shader->info.stage == MESA_SHADER_TESS_CTRL) {4134memory_semantics &= ~(SpvMemorySemanticsAcquireMask |4135SpvMemorySemanticsReleaseMask |4136SpvMemorySemanticsAcquireReleaseMask |4137SpvMemorySemanticsSequentiallyConsistentMask);4138memory_semantics |= SpvMemorySemanticsAcquireReleaseMask |4139SpvMemorySemanticsOutputMemoryMask;4140}41414142if (b->shader->options->use_scoped_barrier) {4143vtn_emit_scoped_control_barrier(b, execution_scope, memory_scope,4144memory_semantics);4145} else {4146vtn_emit_memory_barrier(b, memory_scope, memory_semantics);41474148if (execution_scope == SpvScopeWorkgroup)4149nir_control_barrier(&b->nb);4150}4151break;4152}41534154default:4155unreachable("unknown barrier instruction");4156}4157}41584159static unsigned4160gl_primitive_from_spv_execution_mode(struct vtn_builder *b,4161SpvExecutionMode mode)4162{4163switch (mode) {4164case SpvExecutionModeInputPoints:4165case SpvExecutionModeOutputPoints:4166return 0; /* GL_POINTS */4167case SpvExecutionModeInputLines:4168return 1; /* GL_LINES */4169case SpvExecutionModeInputLinesAdjacency:4170return 0x000A; /* GL_LINE_STRIP_ADJACENCY_ARB */4171case SpvExecutionModeTriangles:4172return 4; /* GL_TRIANGLES */4173case SpvExecutionModeInputTrianglesAdjacency:4174return 0x000C; /* GL_TRIANGLES_ADJACENCY_ARB */4175case SpvExecutionModeQuads:4176return 7; /* GL_QUADS */4177case SpvExecutionModeIsolines:4178return 0x8E7A; /* GL_ISOLINES */4179case SpvExecutionModeOutputLineStrip:4180return 3; /* GL_LINE_STRIP */4181case SpvExecutionModeOutputTriangleStrip:4182return 5; /* GL_TRIANGLE_STRIP */4183default:4184vtn_fail("Invalid primitive type: %s (%u)",4185spirv_executionmode_to_string(mode), mode);4186}4187}41884189static unsigned4190vertices_in_from_spv_execution_mode(struct vtn_builder *b,4191SpvExecutionMode mode)4192{4193switch (mode) {4194case SpvExecutionModeInputPoints:4195return 1;4196case SpvExecutionModeInputLines:4197return 2;4198case SpvExecutionModeInputLinesAdjacency:4199return 4;4200case SpvExecutionModeTriangles:4201return 3;4202case SpvExecutionModeInputTrianglesAdjacency:4203return 6;4204default:4205vtn_fail("Invalid GS input mode: %s (%u)",4206spirv_executionmode_to_string(mode), mode);4207}4208}42094210static gl_shader_stage4211stage_for_execution_model(struct vtn_builder *b, SpvExecutionModel model)4212{4213switch (model) {4214case SpvExecutionModelVertex:4215return MESA_SHADER_VERTEX;4216case SpvExecutionModelTessellationControl:4217return MESA_SHADER_TESS_CTRL;4218case SpvExecutionModelTessellationEvaluation:4219return MESA_SHADER_TESS_EVAL;4220case SpvExecutionModelGeometry:4221return MESA_SHADER_GEOMETRY;4222case SpvExecutionModelFragment:4223return MESA_SHADER_FRAGMENT;4224case SpvExecutionModelGLCompute:4225return MESA_SHADER_COMPUTE;4226case SpvExecutionModelKernel:4227return MESA_SHADER_KERNEL;4228case SpvExecutionModelRayGenerationKHR:4229return MESA_SHADER_RAYGEN;4230case SpvExecutionModelAnyHitKHR:4231return MESA_SHADER_ANY_HIT;4232case SpvExecutionModelClosestHitKHR:4233return MESA_SHADER_CLOSEST_HIT;4234case SpvExecutionModelMissKHR:4235return MESA_SHADER_MISS;4236case SpvExecutionModelIntersectionKHR:4237return MESA_SHADER_INTERSECTION;4238case SpvExecutionModelCallableKHR:4239return MESA_SHADER_CALLABLE;4240default:4241vtn_fail("Unsupported execution model: %s (%u)",4242spirv_executionmodel_to_string(model), model);4243}4244}42454246#define spv_check_supported(name, cap) do { \4247if (!(b->options && b->options->caps.name)) \4248vtn_warn("Unsupported SPIR-V capability: %s (%u)", \4249spirv_capability_to_string(cap), cap); \4250} while(0)425142524253void4254vtn_handle_entry_point(struct vtn_builder *b, const uint32_t *w,4255unsigned count)4256{4257struct vtn_value *entry_point = &b->values[w[2]];4258/* Let this be a name label regardless */4259unsigned name_words;4260entry_point->name = vtn_string_literal(b, &w[3], count - 3, &name_words);42614262if (strcmp(entry_point->name, b->entry_point_name) != 0 ||4263stage_for_execution_model(b, w[1]) != b->entry_point_stage)4264return;42654266vtn_assert(b->entry_point == NULL);4267b->entry_point = entry_point;42684269/* Entry points enumerate which global variables are used. */4270size_t start = 3 + name_words;4271b->interface_ids_count = count - start;4272b->interface_ids = ralloc_array(b, uint32_t, b->interface_ids_count);4273memcpy(b->interface_ids, &w[start], b->interface_ids_count * 4);4274qsort(b->interface_ids, b->interface_ids_count, 4, cmp_uint32_t);4275}42764277static bool4278vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,4279const uint32_t *w, unsigned count)4280{4281switch (opcode) {4282case SpvOpSource: {4283const char *lang;4284switch (w[1]) {4285default:4286case SpvSourceLanguageUnknown: lang = "unknown"; break;4287case SpvSourceLanguageESSL: lang = "ESSL"; break;4288case SpvSourceLanguageGLSL: lang = "GLSL"; break;4289case SpvSourceLanguageOpenCL_C: lang = "OpenCL C"; break;4290case SpvSourceLanguageOpenCL_CPP: lang = "OpenCL C++"; break;4291case SpvSourceLanguageHLSL: lang = "HLSL"; break;4292}42934294uint32_t version = w[2];42954296const char *file =4297(count > 3) ? vtn_value(b, w[3], vtn_value_type_string)->str : "";42984299vtn_info("Parsing SPIR-V from %s %u source file %s", lang, version, file);43004301b->source_lang = w[1];4302break;4303}43044305case SpvOpSourceExtension:4306case SpvOpSourceContinued:4307case SpvOpExtension:4308case SpvOpModuleProcessed:4309/* Unhandled, but these are for debug so that's ok. */4310break;43114312case SpvOpCapability: {4313SpvCapability cap = w[1];4314switch (cap) {4315case SpvCapabilityMatrix:4316case SpvCapabilityShader:4317case SpvCapabilityGeometry:4318case SpvCapabilityGeometryPointSize:4319case SpvCapabilityUniformBufferArrayDynamicIndexing:4320case SpvCapabilitySampledImageArrayDynamicIndexing:4321case SpvCapabilityStorageBufferArrayDynamicIndexing:4322case SpvCapabilityStorageImageArrayDynamicIndexing:4323case SpvCapabilityImageRect:4324case SpvCapabilitySampledRect:4325case SpvCapabilitySampled1D:4326case SpvCapabilityImage1D:4327case SpvCapabilitySampledCubeArray:4328case SpvCapabilityImageCubeArray:4329case SpvCapabilitySampledBuffer:4330case SpvCapabilityImageBuffer:4331case SpvCapabilityImageQuery:4332case SpvCapabilityDerivativeControl:4333case SpvCapabilityInterpolationFunction:4334case SpvCapabilityMultiViewport:4335case SpvCapabilitySampleRateShading:4336case SpvCapabilityClipDistance:4337case SpvCapabilityCullDistance:4338case SpvCapabilityInputAttachment:4339case SpvCapabilityImageGatherExtended:4340case SpvCapabilityStorageImageExtendedFormats:4341case SpvCapabilityVector16:4342break;43434344case SpvCapabilityLinkage:4345if (!b->options->create_library)4346vtn_warn("Unsupported SPIR-V capability: %s",4347spirv_capability_to_string(cap));4348break;43494350case SpvCapabilitySparseResidency:4351spv_check_supported(sparse_residency, cap);4352break;43534354case SpvCapabilityMinLod:4355spv_check_supported(min_lod, cap);4356break;43574358case SpvCapabilityAtomicStorage:4359spv_check_supported(atomic_storage, cap);4360break;43614362case SpvCapabilityFloat64:4363spv_check_supported(float64, cap);4364break;4365case SpvCapabilityInt64:4366spv_check_supported(int64, cap);4367break;4368case SpvCapabilityInt16:4369spv_check_supported(int16, cap);4370break;4371case SpvCapabilityInt8:4372spv_check_supported(int8, cap);4373break;43744375case SpvCapabilityTransformFeedback:4376spv_check_supported(transform_feedback, cap);4377break;43784379case SpvCapabilityGeometryStreams:4380spv_check_supported(geometry_streams, cap);4381break;43824383case SpvCapabilityInt64Atomics:4384spv_check_supported(int64_atomics, cap);4385break;43864387case SpvCapabilityStorageImageMultisample:4388spv_check_supported(storage_image_ms, cap);4389break;43904391case SpvCapabilityAddresses:4392spv_check_supported(address, cap);4393break;43944395case SpvCapabilityKernel:4396case SpvCapabilityFloat16Buffer:4397spv_check_supported(kernel, cap);4398break;43994400case SpvCapabilityGenericPointer:4401spv_check_supported(generic_pointers, cap);4402break;44034404case SpvCapabilityImageBasic:4405spv_check_supported(kernel_image, cap);4406break;44074408case SpvCapabilityImageReadWrite:4409spv_check_supported(kernel_image_read_write, cap);4410break;44114412case SpvCapabilityLiteralSampler:4413spv_check_supported(literal_sampler, cap);4414break;44154416case SpvCapabilityImageMipmap:4417case SpvCapabilityPipes:4418case SpvCapabilityDeviceEnqueue:4419vtn_warn("Unsupported OpenCL-style SPIR-V capability: %s",4420spirv_capability_to_string(cap));4421break;44224423case SpvCapabilityImageMSArray:4424spv_check_supported(image_ms_array, cap);4425break;44264427case SpvCapabilityTessellation:4428case SpvCapabilityTessellationPointSize:4429spv_check_supported(tessellation, cap);4430break;44314432case SpvCapabilityDrawParameters:4433spv_check_supported(draw_parameters, cap);4434break;44354436case SpvCapabilityStorageImageReadWithoutFormat:4437spv_check_supported(image_read_without_format, cap);4438break;44394440case SpvCapabilityStorageImageWriteWithoutFormat:4441spv_check_supported(image_write_without_format, cap);4442break;44434444case SpvCapabilityDeviceGroup:4445spv_check_supported(device_group, cap);4446break;44474448case SpvCapabilityMultiView:4449spv_check_supported(multiview, cap);4450break;44514452case SpvCapabilityGroupNonUniform:4453spv_check_supported(subgroup_basic, cap);4454break;44554456case SpvCapabilitySubgroupVoteKHR:4457case SpvCapabilityGroupNonUniformVote:4458spv_check_supported(subgroup_vote, cap);4459break;44604461case SpvCapabilitySubgroupBallotKHR:4462case SpvCapabilityGroupNonUniformBallot:4463spv_check_supported(subgroup_ballot, cap);4464break;44654466case SpvCapabilityGroupNonUniformShuffle:4467case SpvCapabilityGroupNonUniformShuffleRelative:4468spv_check_supported(subgroup_shuffle, cap);4469break;44704471case SpvCapabilityGroupNonUniformQuad:4472spv_check_supported(subgroup_quad, cap);4473break;44744475case SpvCapabilityGroupNonUniformArithmetic:4476case SpvCapabilityGroupNonUniformClustered:4477spv_check_supported(subgroup_arithmetic, cap);4478break;44794480case SpvCapabilityGroups:4481spv_check_supported(amd_shader_ballot, cap);4482break;44834484case SpvCapabilityVariablePointersStorageBuffer:4485case SpvCapabilityVariablePointers:4486spv_check_supported(variable_pointers, cap);4487b->variable_pointers = true;4488break;44894490case SpvCapabilityStorageUniformBufferBlock16:4491case SpvCapabilityStorageUniform16:4492case SpvCapabilityStoragePushConstant16:4493case SpvCapabilityStorageInputOutput16:4494spv_check_supported(storage_16bit, cap);4495break;44964497case SpvCapabilityShaderLayer:4498case SpvCapabilityShaderViewportIndex:4499case SpvCapabilityShaderViewportIndexLayerEXT:4500spv_check_supported(shader_viewport_index_layer, cap);4501break;45024503case SpvCapabilityStorageBuffer8BitAccess:4504case SpvCapabilityUniformAndStorageBuffer8BitAccess:4505case SpvCapabilityStoragePushConstant8:4506spv_check_supported(storage_8bit, cap);4507break;45084509case SpvCapabilityShaderNonUniformEXT:4510spv_check_supported(descriptor_indexing, cap);4511break;45124513case SpvCapabilityInputAttachmentArrayDynamicIndexingEXT:4514case SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT:4515case SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT:4516spv_check_supported(descriptor_array_dynamic_indexing, cap);4517break;45184519case SpvCapabilityUniformBufferArrayNonUniformIndexingEXT:4520case SpvCapabilitySampledImageArrayNonUniformIndexingEXT:4521case SpvCapabilityStorageBufferArrayNonUniformIndexingEXT:4522case SpvCapabilityStorageImageArrayNonUniformIndexingEXT:4523case SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT:4524case SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT:4525case SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT:4526spv_check_supported(descriptor_array_non_uniform_indexing, cap);4527break;45284529case SpvCapabilityRuntimeDescriptorArrayEXT:4530spv_check_supported(runtime_descriptor_array, cap);4531break;45324533case SpvCapabilityStencilExportEXT:4534spv_check_supported(stencil_export, cap);4535break;45364537case SpvCapabilitySampleMaskPostDepthCoverage:4538spv_check_supported(post_depth_coverage, cap);4539break;45404541case SpvCapabilityDenormFlushToZero:4542case SpvCapabilityDenormPreserve:4543case SpvCapabilitySignedZeroInfNanPreserve:4544case SpvCapabilityRoundingModeRTE:4545case SpvCapabilityRoundingModeRTZ:4546spv_check_supported(float_controls, cap);4547break;45484549case SpvCapabilityPhysicalStorageBufferAddresses:4550spv_check_supported(physical_storage_buffer_address, cap);4551break;45524553case SpvCapabilityComputeDerivativeGroupQuadsNV:4554case SpvCapabilityComputeDerivativeGroupLinearNV:4555spv_check_supported(derivative_group, cap);4556break;45574558case SpvCapabilityFloat16:4559spv_check_supported(float16, cap);4560break;45614562case SpvCapabilityFragmentShaderSampleInterlockEXT:4563spv_check_supported(fragment_shader_sample_interlock, cap);4564break;45654566case SpvCapabilityFragmentShaderPixelInterlockEXT:4567spv_check_supported(fragment_shader_pixel_interlock, cap);4568break;45694570case SpvCapabilityDemoteToHelperInvocationEXT:4571spv_check_supported(demote_to_helper_invocation, cap);4572b->uses_demote_to_helper_invocation = true;4573break;45744575case SpvCapabilityShaderClockKHR:4576spv_check_supported(shader_clock, cap);4577break;45784579case SpvCapabilityVulkanMemoryModel:4580spv_check_supported(vk_memory_model, cap);4581break;45824583case SpvCapabilityVulkanMemoryModelDeviceScope:4584spv_check_supported(vk_memory_model_device_scope, cap);4585break;45864587case SpvCapabilityImageReadWriteLodAMD:4588spv_check_supported(amd_image_read_write_lod, cap);4589break;45904591case SpvCapabilityIntegerFunctions2INTEL:4592spv_check_supported(integer_functions2, cap);4593break;45944595case SpvCapabilityFragmentMaskAMD:4596spv_check_supported(amd_fragment_mask, cap);4597break;45984599case SpvCapabilityImageGatherBiasLodAMD:4600spv_check_supported(amd_image_gather_bias_lod, cap);4601break;46024603case SpvCapabilityAtomicFloat32AddEXT:4604spv_check_supported(float32_atomic_add, cap);4605break;46064607case SpvCapabilityAtomicFloat64AddEXT:4608spv_check_supported(float64_atomic_add, cap);4609break;46104611case SpvCapabilitySubgroupShuffleINTEL:4612spv_check_supported(intel_subgroup_shuffle, cap);4613break;46144615case SpvCapabilitySubgroupBufferBlockIOINTEL:4616spv_check_supported(intel_subgroup_buffer_block_io, cap);4617break;46184619case SpvCapabilityRayTracingKHR:4620spv_check_supported(ray_tracing, cap);4621break;46224623case SpvCapabilityRayQueryKHR:4624spv_check_supported(ray_query, cap);4625break;46264627case SpvCapabilityRayTraversalPrimitiveCullingKHR:4628spv_check_supported(ray_traversal_primitive_culling, cap);4629break;46304631case SpvCapabilityInt64ImageEXT:4632spv_check_supported(image_atomic_int64, cap);4633break;46344635case SpvCapabilityFragmentShadingRateKHR:4636spv_check_supported(fragment_shading_rate, cap);4637break;46384639case SpvCapabilityWorkgroupMemoryExplicitLayoutKHR:4640spv_check_supported(workgroup_memory_explicit_layout, cap);4641break;46424643case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:4644spv_check_supported(workgroup_memory_explicit_layout, cap);4645spv_check_supported(storage_8bit, cap);4646break;46474648case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:4649spv_check_supported(workgroup_memory_explicit_layout, cap);4650spv_check_supported(storage_16bit, cap);4651break;46524653case SpvCapabilityAtomicFloat16MinMaxEXT:4654spv_check_supported(float16_atomic_min_max, cap);4655break;46564657case SpvCapabilityAtomicFloat32MinMaxEXT:4658spv_check_supported(float32_atomic_min_max, cap);4659break;46604661case SpvCapabilityAtomicFloat64MinMaxEXT:4662spv_check_supported(float64_atomic_min_max, cap);4663break;46644665default:4666vtn_fail("Unhandled capability: %s (%u)",4667spirv_capability_to_string(cap), cap);4668}4669break;4670}46714672case SpvOpExtInstImport:4673vtn_handle_extension(b, opcode, w, count);4674break;46754676case SpvOpMemoryModel:4677switch (w[1]) {4678case SpvAddressingModelPhysical32:4679vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,4680"AddressingModelPhysical32 only supported for kernels");4681b->shader->info.cs.ptr_size = 32;4682b->physical_ptrs = true;4683assert(nir_address_format_bit_size(b->options->global_addr_format) == 32);4684assert(nir_address_format_num_components(b->options->global_addr_format) == 1);4685assert(nir_address_format_bit_size(b->options->shared_addr_format) == 32);4686assert(nir_address_format_num_components(b->options->shared_addr_format) == 1);4687assert(nir_address_format_bit_size(b->options->constant_addr_format) == 32);4688assert(nir_address_format_num_components(b->options->constant_addr_format) == 1);4689break;4690case SpvAddressingModelPhysical64:4691vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,4692"AddressingModelPhysical64 only supported for kernels");4693b->shader->info.cs.ptr_size = 64;4694b->physical_ptrs = true;4695assert(nir_address_format_bit_size(b->options->global_addr_format) == 64);4696assert(nir_address_format_num_components(b->options->global_addr_format) == 1);4697assert(nir_address_format_bit_size(b->options->shared_addr_format) == 64);4698assert(nir_address_format_num_components(b->options->shared_addr_format) == 1);4699assert(nir_address_format_bit_size(b->options->constant_addr_format) == 64);4700assert(nir_address_format_num_components(b->options->constant_addr_format) == 1);4701break;4702case SpvAddressingModelLogical:4703vtn_fail_if(b->shader->info.stage == MESA_SHADER_KERNEL,4704"AddressingModelLogical only supported for shaders");4705b->physical_ptrs = false;4706break;4707case SpvAddressingModelPhysicalStorageBuffer64:4708vtn_fail_if(!b->options ||4709!b->options->caps.physical_storage_buffer_address,4710"AddressingModelPhysicalStorageBuffer64 not supported");4711break;4712default:4713vtn_fail("Unknown addressing model: %s (%u)",4714spirv_addressingmodel_to_string(w[1]), w[1]);4715break;4716}47174718b->mem_model = w[2];4719switch (w[2]) {4720case SpvMemoryModelSimple:4721case SpvMemoryModelGLSL450:4722case SpvMemoryModelOpenCL:4723break;4724case SpvMemoryModelVulkan:4725vtn_fail_if(!b->options->caps.vk_memory_model,4726"Vulkan memory model is unsupported by this driver");4727break;4728default:4729vtn_fail("Unsupported memory model: %s",4730spirv_memorymodel_to_string(w[2]));4731break;4732}4733break;47344735case SpvOpEntryPoint:4736vtn_handle_entry_point(b, w, count);4737break;47384739case SpvOpString:4740vtn_push_value(b, w[1], vtn_value_type_string)->str =4741vtn_string_literal(b, &w[2], count - 2, NULL);4742break;47434744case SpvOpName:4745b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2, NULL);4746break;47474748case SpvOpMemberName:4749/* TODO */4750break;47514752case SpvOpExecutionMode:4753case SpvOpExecutionModeId:4754case SpvOpDecorationGroup:4755case SpvOpDecorate:4756case SpvOpDecorateId:4757case SpvOpMemberDecorate:4758case SpvOpGroupDecorate:4759case SpvOpGroupMemberDecorate:4760case SpvOpDecorateString:4761case SpvOpMemberDecorateString:4762vtn_handle_decoration(b, opcode, w, count);4763break;47644765case SpvOpExtInst: {4766struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_extension);4767if (val->ext_handler == vtn_handle_non_semantic_instruction) {4768/* NonSemantic extended instructions are acceptable in preamble. */4769vtn_handle_non_semantic_instruction(b, w[4], w, count);4770return true;4771} else {4772return false; /* End of preamble. */4773}4774}47754776default:4777return false; /* End of preamble */4778}47794780return true;4781}47824783static void4784vtn_handle_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point,4785const struct vtn_decoration *mode, UNUSED void *data)4786{4787vtn_assert(b->entry_point == entry_point);47884789switch(mode->exec_mode) {4790case SpvExecutionModeOriginUpperLeft:4791case SpvExecutionModeOriginLowerLeft:4792vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4793b->shader->info.fs.origin_upper_left =4794(mode->exec_mode == SpvExecutionModeOriginUpperLeft);4795break;47964797case SpvExecutionModeEarlyFragmentTests:4798vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4799b->shader->info.fs.early_fragment_tests = true;4800break;48014802case SpvExecutionModePostDepthCoverage:4803vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4804b->shader->info.fs.post_depth_coverage = true;4805break;48064807case SpvExecutionModeInvocations:4808vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);4809b->shader->info.gs.invocations = MAX2(1, mode->operands[0]);4810break;48114812case SpvExecutionModeDepthReplacing:4813vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4814b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_ANY;4815break;4816case SpvExecutionModeDepthGreater:4817vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4818b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_GREATER;4819break;4820case SpvExecutionModeDepthLess:4821vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4822b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_LESS;4823break;4824case SpvExecutionModeDepthUnchanged:4825vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4826b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_UNCHANGED;4827break;48284829case SpvExecutionModeLocalSizeHint:4830vtn_assert(b->shader->info.stage == MESA_SHADER_KERNEL);4831b->shader->info.cs.workgroup_size_hint[0] = mode->operands[0];4832b->shader->info.cs.workgroup_size_hint[1] = mode->operands[1];4833b->shader->info.cs.workgroup_size_hint[2] = mode->operands[2];4834break;48354836case SpvExecutionModeLocalSize:4837vtn_assert(gl_shader_stage_is_compute(b->shader->info.stage));4838b->shader->info.workgroup_size[0] = mode->operands[0];4839b->shader->info.workgroup_size[1] = mode->operands[1];4840b->shader->info.workgroup_size[2] = mode->operands[2];4841break;48424843case SpvExecutionModeOutputVertices:4844if (b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4845b->shader->info.stage == MESA_SHADER_TESS_EVAL) {4846b->shader->info.tess.tcs_vertices_out = mode->operands[0];4847} else {4848vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);4849b->shader->info.gs.vertices_out = mode->operands[0];4850}4851break;48524853case SpvExecutionModeInputPoints:4854case SpvExecutionModeInputLines:4855case SpvExecutionModeInputLinesAdjacency:4856case SpvExecutionModeTriangles:4857case SpvExecutionModeInputTrianglesAdjacency:4858case SpvExecutionModeQuads:4859case SpvExecutionModeIsolines:4860if (b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4861b->shader->info.stage == MESA_SHADER_TESS_EVAL) {4862b->shader->info.tess.primitive_mode =4863gl_primitive_from_spv_execution_mode(b, mode->exec_mode);4864} else {4865vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);4866b->shader->info.gs.vertices_in =4867vertices_in_from_spv_execution_mode(b, mode->exec_mode);4868b->shader->info.gs.input_primitive =4869gl_primitive_from_spv_execution_mode(b, mode->exec_mode);4870}4871break;48724873case SpvExecutionModeOutputPoints:4874case SpvExecutionModeOutputLineStrip:4875case SpvExecutionModeOutputTriangleStrip:4876vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);4877b->shader->info.gs.output_primitive =4878gl_primitive_from_spv_execution_mode(b, mode->exec_mode);4879break;48804881case SpvExecutionModeSpacingEqual:4882vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4883b->shader->info.stage == MESA_SHADER_TESS_EVAL);4884b->shader->info.tess.spacing = TESS_SPACING_EQUAL;4885break;4886case SpvExecutionModeSpacingFractionalEven:4887vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4888b->shader->info.stage == MESA_SHADER_TESS_EVAL);4889b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_EVEN;4890break;4891case SpvExecutionModeSpacingFractionalOdd:4892vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4893b->shader->info.stage == MESA_SHADER_TESS_EVAL);4894b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_ODD;4895break;4896case SpvExecutionModeVertexOrderCw:4897vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4898b->shader->info.stage == MESA_SHADER_TESS_EVAL);4899b->shader->info.tess.ccw = false;4900break;4901case SpvExecutionModeVertexOrderCcw:4902vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4903b->shader->info.stage == MESA_SHADER_TESS_EVAL);4904b->shader->info.tess.ccw = true;4905break;4906case SpvExecutionModePointMode:4907vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||4908b->shader->info.stage == MESA_SHADER_TESS_EVAL);4909b->shader->info.tess.point_mode = true;4910break;49114912case SpvExecutionModePixelCenterInteger:4913vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4914b->shader->info.fs.pixel_center_integer = true;4915break;49164917case SpvExecutionModeXfb:4918b->shader->info.has_transform_feedback_varyings = true;4919break;49204921case SpvExecutionModeVecTypeHint:4922break; /* OpenCL */49234924case SpvExecutionModeContractionOff:4925if (b->shader->info.stage != MESA_SHADER_KERNEL)4926vtn_warn("ExectionMode only allowed for CL-style kernels: %s",4927spirv_executionmode_to_string(mode->exec_mode));4928else4929b->exact = true;4930break;49314932case SpvExecutionModeStencilRefReplacingEXT:4933vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4934break;49354936case SpvExecutionModeDerivativeGroupQuadsNV:4937vtn_assert(b->shader->info.stage == MESA_SHADER_COMPUTE);4938b->shader->info.cs.derivative_group = DERIVATIVE_GROUP_QUADS;4939break;49404941case SpvExecutionModeDerivativeGroupLinearNV:4942vtn_assert(b->shader->info.stage == MESA_SHADER_COMPUTE);4943b->shader->info.cs.derivative_group = DERIVATIVE_GROUP_LINEAR;4944break;49454946case SpvExecutionModePixelInterlockOrderedEXT:4947vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4948b->shader->info.fs.pixel_interlock_ordered = true;4949break;49504951case SpvExecutionModePixelInterlockUnorderedEXT:4952vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4953b->shader->info.fs.pixel_interlock_unordered = true;4954break;49554956case SpvExecutionModeSampleInterlockOrderedEXT:4957vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4958b->shader->info.fs.sample_interlock_ordered = true;4959break;49604961case SpvExecutionModeSampleInterlockUnorderedEXT:4962vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);4963b->shader->info.fs.sample_interlock_unordered = true;4964break;49654966case SpvExecutionModeDenormPreserve:4967case SpvExecutionModeDenormFlushToZero:4968case SpvExecutionModeSignedZeroInfNanPreserve:4969case SpvExecutionModeRoundingModeRTE:4970case SpvExecutionModeRoundingModeRTZ: {4971unsigned execution_mode = 0;4972switch (mode->exec_mode) {4973case SpvExecutionModeDenormPreserve:4974switch (mode->operands[0]) {4975case 16: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP16; break;4976case 32: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP32; break;4977case 64: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP64; break;4978default: vtn_fail("Floating point type not supported");4979}4980break;4981case SpvExecutionModeDenormFlushToZero:4982switch (mode->operands[0]) {4983case 16: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP16; break;4984case 32: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP32; break;4985case 64: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP64; break;4986default: vtn_fail("Floating point type not supported");4987}4988break;4989case SpvExecutionModeSignedZeroInfNanPreserve:4990switch (mode->operands[0]) {4991case 16: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP16; break;4992case 32: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP32; break;4993case 64: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP64; break;4994default: vtn_fail("Floating point type not supported");4995}4996break;4997case SpvExecutionModeRoundingModeRTE:4998switch (mode->operands[0]) {4999case 16: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP16; break;5000case 32: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP32; break;5001case 64: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP64; break;5002default: vtn_fail("Floating point type not supported");5003}5004break;5005case SpvExecutionModeRoundingModeRTZ:5006switch (mode->operands[0]) {5007case 16: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP16; break;5008case 32: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP32; break;5009case 64: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP64; break;5010default: vtn_fail("Floating point type not supported");5011}5012break;5013default:5014break;5015}50165017b->shader->info.float_controls_execution_mode |= execution_mode;50185019for (unsigned bit_size = 16; bit_size <= 64; bit_size *= 2) {5020vtn_fail_if(nir_is_denorm_flush_to_zero(b->shader->info.float_controls_execution_mode, bit_size) &&5021nir_is_denorm_preserve(b->shader->info.float_controls_execution_mode, bit_size),5022"Cannot flush to zero and preserve denorms for the same bit size.");5023vtn_fail_if(nir_is_rounding_mode_rtne(b->shader->info.float_controls_execution_mode, bit_size) &&5024nir_is_rounding_mode_rtz(b->shader->info.float_controls_execution_mode, bit_size),5025"Cannot set rounding mode to RTNE and RTZ for the same bit size.");5026}5027break;5028}50295030case SpvExecutionModeLocalSizeId:5031case SpvExecutionModeLocalSizeHintId:5032/* Handled later by vtn_handle_execution_mode_id(). */5033break;50345035case SpvExecutionModeSubgroupUniformControlFlowKHR:5036/* There's no corresponding SPIR-V capability, so check here. */5037vtn_fail_if(!b->options->caps.subgroup_uniform_control_flow,5038"SpvExecutionModeSubgroupUniformControlFlowKHR not supported.");5039break;50405041default:5042vtn_fail("Unhandled execution mode: %s (%u)",5043spirv_executionmode_to_string(mode->exec_mode),5044mode->exec_mode);5045}5046}50475048static void5049vtn_handle_execution_mode_id(struct vtn_builder *b, struct vtn_value *entry_point,5050const struct vtn_decoration *mode, UNUSED void *data)5051{50525053vtn_assert(b->entry_point == entry_point);50545055switch (mode->exec_mode) {5056case SpvExecutionModeLocalSizeId:5057b->shader->info.workgroup_size[0] = vtn_constant_uint(b, mode->operands[0]);5058b->shader->info.workgroup_size[1] = vtn_constant_uint(b, mode->operands[1]);5059b->shader->info.workgroup_size[2] = vtn_constant_uint(b, mode->operands[2]);5060break;50615062case SpvExecutionModeLocalSizeHintId:5063vtn_assert(b->shader->info.stage == MESA_SHADER_KERNEL);5064b->shader->info.cs.workgroup_size_hint[0] = vtn_constant_uint(b, mode->operands[0]);5065b->shader->info.cs.workgroup_size_hint[1] = vtn_constant_uint(b, mode->operands[1]);5066b->shader->info.cs.workgroup_size_hint[2] = vtn_constant_uint(b, mode->operands[2]);5067break;50685069default:5070/* Nothing to do. Literal execution modes already handled by5071* vtn_handle_execution_mode(). */5072break;5073}5074}50755076static bool5077vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,5078const uint32_t *w, unsigned count)5079{5080vtn_set_instruction_result_type(b, opcode, w, count);50815082switch (opcode) {5083case SpvOpSource:5084case SpvOpSourceContinued:5085case SpvOpSourceExtension:5086case SpvOpExtension:5087case SpvOpCapability:5088case SpvOpExtInstImport:5089case SpvOpMemoryModel:5090case SpvOpEntryPoint:5091case SpvOpExecutionMode:5092case SpvOpString:5093case SpvOpName:5094case SpvOpMemberName:5095case SpvOpDecorationGroup:5096case SpvOpDecorate:5097case SpvOpDecorateId:5098case SpvOpMemberDecorate:5099case SpvOpGroupDecorate:5100case SpvOpGroupMemberDecorate:5101case SpvOpDecorateString:5102case SpvOpMemberDecorateString:5103vtn_fail("Invalid opcode types and variables section");5104break;51055106case SpvOpTypeVoid:5107case SpvOpTypeBool:5108case SpvOpTypeInt:5109case SpvOpTypeFloat:5110case SpvOpTypeVector:5111case SpvOpTypeMatrix:5112case SpvOpTypeImage:5113case SpvOpTypeSampler:5114case SpvOpTypeSampledImage:5115case SpvOpTypeArray:5116case SpvOpTypeRuntimeArray:5117case SpvOpTypeStruct:5118case SpvOpTypeOpaque:5119case SpvOpTypePointer:5120case SpvOpTypeForwardPointer:5121case SpvOpTypeFunction:5122case SpvOpTypeEvent:5123case SpvOpTypeDeviceEvent:5124case SpvOpTypeReserveId:5125case SpvOpTypeQueue:5126case SpvOpTypePipe:5127case SpvOpTypeAccelerationStructureKHR:5128vtn_handle_type(b, opcode, w, count);5129break;51305131case SpvOpConstantTrue:5132case SpvOpConstantFalse:5133case SpvOpConstant:5134case SpvOpConstantComposite:5135case SpvOpConstantNull:5136case SpvOpSpecConstantTrue:5137case SpvOpSpecConstantFalse:5138case SpvOpSpecConstant:5139case SpvOpSpecConstantComposite:5140case SpvOpSpecConstantOp:5141vtn_handle_constant(b, opcode, w, count);5142break;51435144case SpvOpUndef:5145case SpvOpVariable:5146case SpvOpConstantSampler:5147vtn_handle_variables(b, opcode, w, count);5148break;51495150case SpvOpExtInst: {5151struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_extension);5152/* NonSemantic extended instructions are acceptable in preamble, others5153* will indicate the end of preamble.5154*/5155return val->ext_handler == vtn_handle_non_semantic_instruction;5156}51575158default:5159return false; /* End of preamble */5160}51615162return true;5163}51645165static struct vtn_ssa_value *5166vtn_nir_select(struct vtn_builder *b, struct vtn_ssa_value *src0,5167struct vtn_ssa_value *src1, struct vtn_ssa_value *src2)5168{5169struct vtn_ssa_value *dest = rzalloc(b, struct vtn_ssa_value);5170dest->type = src1->type;51715172if (glsl_type_is_vector_or_scalar(src1->type)) {5173dest->def = nir_bcsel(&b->nb, src0->def, src1->def, src2->def);5174} else {5175unsigned elems = glsl_get_length(src1->type);51765177dest->elems = ralloc_array(b, struct vtn_ssa_value *, elems);5178for (unsigned i = 0; i < elems; i++) {5179dest->elems[i] = vtn_nir_select(b, src0,5180src1->elems[i], src2->elems[i]);5181}5182}51835184return dest;5185}51865187static void5188vtn_handle_select(struct vtn_builder *b, SpvOp opcode,5189const uint32_t *w, unsigned count)5190{5191/* Handle OpSelect up-front here because it needs to be able to handle5192* pointers and not just regular vectors and scalars.5193*/5194struct vtn_value *res_val = vtn_untyped_value(b, w[2]);5195struct vtn_value *cond_val = vtn_untyped_value(b, w[3]);5196struct vtn_value *obj1_val = vtn_untyped_value(b, w[4]);5197struct vtn_value *obj2_val = vtn_untyped_value(b, w[5]);51985199vtn_fail_if(obj1_val->type != res_val->type ||5200obj2_val->type != res_val->type,5201"Object types must match the result type in OpSelect");52025203vtn_fail_if((cond_val->type->base_type != vtn_base_type_scalar &&5204cond_val->type->base_type != vtn_base_type_vector) ||5205!glsl_type_is_boolean(cond_val->type->type),5206"OpSelect must have either a vector of booleans or "5207"a boolean as Condition type");52085209vtn_fail_if(cond_val->type->base_type == vtn_base_type_vector &&5210(res_val->type->base_type != vtn_base_type_vector ||5211res_val->type->length != cond_val->type->length),5212"When Condition type in OpSelect is a vector, the Result "5213"type must be a vector of the same length");52145215switch (res_val->type->base_type) {5216case vtn_base_type_scalar:5217case vtn_base_type_vector:5218case vtn_base_type_matrix:5219case vtn_base_type_array:5220case vtn_base_type_struct:5221/* OK. */5222break;5223case vtn_base_type_pointer:5224/* We need to have actual storage for pointer types. */5225vtn_fail_if(res_val->type->type == NULL,5226"Invalid pointer result type for OpSelect");5227break;5228default:5229vtn_fail("Result type of OpSelect must be a scalar, composite, or pointer");5230}52315232vtn_push_ssa_value(b, w[2],5233vtn_nir_select(b, vtn_ssa_value(b, w[3]),5234vtn_ssa_value(b, w[4]),5235vtn_ssa_value(b, w[5])));5236}52375238static void5239vtn_handle_ptr(struct vtn_builder *b, SpvOp opcode,5240const uint32_t *w, unsigned count)5241{5242struct vtn_type *type1 = vtn_get_value_type(b, w[3]);5243struct vtn_type *type2 = vtn_get_value_type(b, w[4]);5244vtn_fail_if(type1->base_type != vtn_base_type_pointer ||5245type2->base_type != vtn_base_type_pointer,5246"%s operands must have pointer types",5247spirv_op_to_string(opcode));5248vtn_fail_if(type1->storage_class != type2->storage_class,5249"%s operands must have the same storage class",5250spirv_op_to_string(opcode));52515252struct vtn_type *vtn_type = vtn_get_type(b, w[1]);5253const struct glsl_type *type = vtn_type->type;52545255nir_address_format addr_format = vtn_mode_to_address_format(5256b, vtn_storage_class_to_mode(b, type1->storage_class, NULL, NULL));52575258nir_ssa_def *def;52595260switch (opcode) {5261case SpvOpPtrDiff: {5262/* OpPtrDiff returns the difference in number of elements (not byte offset). */5263unsigned elem_size, elem_align;5264glsl_get_natural_size_align_bytes(type1->deref->type,5265&elem_size, &elem_align);52665267def = nir_build_addr_isub(&b->nb,5268vtn_get_nir_ssa(b, w[3]),5269vtn_get_nir_ssa(b, w[4]),5270addr_format);5271def = nir_idiv(&b->nb, def, nir_imm_intN_t(&b->nb, elem_size, def->bit_size));5272def = nir_i2i(&b->nb, def, glsl_get_bit_size(type));5273break;5274}52755276case SpvOpPtrEqual:5277case SpvOpPtrNotEqual: {5278def = nir_build_addr_ieq(&b->nb,5279vtn_get_nir_ssa(b, w[3]),5280vtn_get_nir_ssa(b, w[4]),5281addr_format);5282if (opcode == SpvOpPtrNotEqual)5283def = nir_inot(&b->nb, def);5284break;5285}52865287default:5288unreachable("Invalid ptr operation");5289}52905291vtn_push_nir_ssa(b, w[2], def);5292}52935294static void5295vtn_handle_ray_intrinsic(struct vtn_builder *b, SpvOp opcode,5296const uint32_t *w, unsigned count)5297{5298nir_intrinsic_instr *intrin;52995300switch (opcode) {5301case SpvOpTraceNV:5302case SpvOpTraceRayKHR: {5303intrin = nir_intrinsic_instr_create(b->nb.shader,5304nir_intrinsic_trace_ray);53055306/* The sources are in the same order in the NIR intrinsic */5307for (unsigned i = 0; i < 10; i++)5308intrin->src[i] = nir_src_for_ssa(vtn_ssa_value(b, w[i + 1])->def);53095310nir_deref_instr *payload;5311if (opcode == SpvOpTraceNV)5312payload = vtn_get_call_payload_for_location(b, w[11]);5313else5314payload = vtn_nir_deref(b, w[11]);5315intrin->src[10] = nir_src_for_ssa(&payload->dest.ssa);5316nir_builder_instr_insert(&b->nb, &intrin->instr);5317break;5318}53195320case SpvOpReportIntersectionKHR: {5321intrin = nir_intrinsic_instr_create(b->nb.shader,5322nir_intrinsic_report_ray_intersection);5323intrin->src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[3])->def);5324intrin->src[1] = nir_src_for_ssa(vtn_ssa_value(b, w[4])->def);5325nir_ssa_dest_init(&intrin->instr, &intrin->dest, 1, 1, NULL);5326nir_builder_instr_insert(&b->nb, &intrin->instr);5327vtn_push_nir_ssa(b, w[2], &intrin->dest.ssa);5328break;5329}53305331case SpvOpIgnoreIntersectionNV:5332intrin = nir_intrinsic_instr_create(b->nb.shader,5333nir_intrinsic_ignore_ray_intersection);5334nir_builder_instr_insert(&b->nb, &intrin->instr);5335break;53365337case SpvOpTerminateRayNV:5338intrin = nir_intrinsic_instr_create(b->nb.shader,5339nir_intrinsic_terminate_ray);5340nir_builder_instr_insert(&b->nb, &intrin->instr);5341break;53425343case SpvOpExecuteCallableNV:5344case SpvOpExecuteCallableKHR: {5345intrin = nir_intrinsic_instr_create(b->nb.shader,5346nir_intrinsic_execute_callable);5347intrin->src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[1])->def);5348nir_deref_instr *payload;5349if (opcode == SpvOpExecuteCallableNV)5350payload = vtn_get_call_payload_for_location(b, w[2]);5351else5352payload = vtn_nir_deref(b, w[2]);5353intrin->src[1] = nir_src_for_ssa(&payload->dest.ssa);5354nir_builder_instr_insert(&b->nb, &intrin->instr);5355break;5356}53575358default:5359vtn_fail_with_opcode("Unhandled opcode", opcode);5360}5361}53625363static bool5364vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,5365const uint32_t *w, unsigned count)5366{5367switch (opcode) {5368case SpvOpLabel:5369break;53705371case SpvOpLoopMerge:5372case SpvOpSelectionMerge:5373/* This is handled by cfg pre-pass and walk_blocks */5374break;53755376case SpvOpUndef: {5377struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);5378val->type = vtn_get_type(b, w[1]);5379break;5380}53815382case SpvOpExtInst:5383vtn_handle_extension(b, opcode, w, count);5384break;53855386case SpvOpVariable:5387case SpvOpLoad:5388case SpvOpStore:5389case SpvOpCopyMemory:5390case SpvOpCopyMemorySized:5391case SpvOpAccessChain:5392case SpvOpPtrAccessChain:5393case SpvOpInBoundsAccessChain:5394case SpvOpInBoundsPtrAccessChain:5395case SpvOpArrayLength:5396case SpvOpConvertPtrToU:5397case SpvOpConvertUToPtr:5398case SpvOpGenericCastToPtrExplicit:5399case SpvOpGenericPtrMemSemantics:5400case SpvOpSubgroupBlockReadINTEL:5401case SpvOpSubgroupBlockWriteINTEL:5402case SpvOpConvertUToAccelerationStructureKHR:5403vtn_handle_variables(b, opcode, w, count);5404break;54055406case SpvOpFunctionCall:5407vtn_handle_function_call(b, opcode, w, count);5408break;54095410case SpvOpSampledImage:5411case SpvOpImage:5412case SpvOpImageSparseTexelsResident:5413case SpvOpImageSampleImplicitLod:5414case SpvOpImageSparseSampleImplicitLod:5415case SpvOpImageSampleExplicitLod:5416case SpvOpImageSparseSampleExplicitLod:5417case SpvOpImageSampleDrefImplicitLod:5418case SpvOpImageSparseSampleDrefImplicitLod:5419case SpvOpImageSampleDrefExplicitLod:5420case SpvOpImageSparseSampleDrefExplicitLod:5421case SpvOpImageSampleProjImplicitLod:5422case SpvOpImageSampleProjExplicitLod:5423case SpvOpImageSampleProjDrefImplicitLod:5424case SpvOpImageSampleProjDrefExplicitLod:5425case SpvOpImageFetch:5426case SpvOpImageSparseFetch:5427case SpvOpImageGather:5428case SpvOpImageSparseGather:5429case SpvOpImageDrefGather:5430case SpvOpImageSparseDrefGather:5431case SpvOpImageQueryLod:5432case SpvOpImageQueryLevels:5433vtn_handle_texture(b, opcode, w, count);5434break;54355436case SpvOpImageRead:5437case SpvOpImageSparseRead:5438case SpvOpImageWrite:5439case SpvOpImageTexelPointer:5440case SpvOpImageQueryFormat:5441case SpvOpImageQueryOrder:5442vtn_handle_image(b, opcode, w, count);5443break;54445445case SpvOpImageQuerySamples:5446case SpvOpImageQuerySizeLod:5447case SpvOpImageQuerySize: {5448struct vtn_type *image_type = vtn_get_value_type(b, w[3]);5449vtn_assert(image_type->base_type == vtn_base_type_image);5450if (glsl_type_is_image(image_type->glsl_image)) {5451vtn_handle_image(b, opcode, w, count);5452} else {5453vtn_assert(glsl_type_is_sampler(image_type->glsl_image));5454vtn_handle_texture(b, opcode, w, count);5455}5456break;5457}54585459case SpvOpFragmentMaskFetchAMD:5460case SpvOpFragmentFetchAMD:5461vtn_handle_texture(b, opcode, w, count);5462break;54635464case SpvOpAtomicLoad:5465case SpvOpAtomicExchange:5466case SpvOpAtomicCompareExchange:5467case SpvOpAtomicCompareExchangeWeak:5468case SpvOpAtomicIIncrement:5469case SpvOpAtomicIDecrement:5470case SpvOpAtomicIAdd:5471case SpvOpAtomicISub:5472case SpvOpAtomicSMin:5473case SpvOpAtomicUMin:5474case SpvOpAtomicSMax:5475case SpvOpAtomicUMax:5476case SpvOpAtomicAnd:5477case SpvOpAtomicOr:5478case SpvOpAtomicXor:5479case SpvOpAtomicFAddEXT:5480case SpvOpAtomicFMinEXT:5481case SpvOpAtomicFMaxEXT: {5482struct vtn_value *pointer = vtn_untyped_value(b, w[3]);5483if (pointer->value_type == vtn_value_type_image_pointer) {5484vtn_handle_image(b, opcode, w, count);5485} else {5486vtn_assert(pointer->value_type == vtn_value_type_pointer);5487vtn_handle_atomics(b, opcode, w, count);5488}5489break;5490}54915492case SpvOpAtomicStore: {5493struct vtn_value *pointer = vtn_untyped_value(b, w[1]);5494if (pointer->value_type == vtn_value_type_image_pointer) {5495vtn_handle_image(b, opcode, w, count);5496} else {5497vtn_assert(pointer->value_type == vtn_value_type_pointer);5498vtn_handle_atomics(b, opcode, w, count);5499}5500break;5501}55025503case SpvOpSelect:5504vtn_handle_select(b, opcode, w, count);5505break;55065507case SpvOpSNegate:5508case SpvOpFNegate:5509case SpvOpNot:5510case SpvOpAny:5511case SpvOpAll:5512case SpvOpConvertFToU:5513case SpvOpConvertFToS:5514case SpvOpConvertSToF:5515case SpvOpConvertUToF:5516case SpvOpUConvert:5517case SpvOpSConvert:5518case SpvOpFConvert:5519case SpvOpQuantizeToF16:5520case SpvOpSatConvertSToU:5521case SpvOpSatConvertUToS:5522case SpvOpPtrCastToGeneric:5523case SpvOpGenericCastToPtr:5524case SpvOpIsNan:5525case SpvOpIsInf:5526case SpvOpIsFinite:5527case SpvOpIsNormal:5528case SpvOpSignBitSet:5529case SpvOpLessOrGreater:5530case SpvOpOrdered:5531case SpvOpUnordered:5532case SpvOpIAdd:5533case SpvOpFAdd:5534case SpvOpISub:5535case SpvOpFSub:5536case SpvOpIMul:5537case SpvOpFMul:5538case SpvOpUDiv:5539case SpvOpSDiv:5540case SpvOpFDiv:5541case SpvOpUMod:5542case SpvOpSRem:5543case SpvOpSMod:5544case SpvOpFRem:5545case SpvOpFMod:5546case SpvOpVectorTimesScalar:5547case SpvOpDot:5548case SpvOpIAddCarry:5549case SpvOpISubBorrow:5550case SpvOpUMulExtended:5551case SpvOpSMulExtended:5552case SpvOpShiftRightLogical:5553case SpvOpShiftRightArithmetic:5554case SpvOpShiftLeftLogical:5555case SpvOpLogicalEqual:5556case SpvOpLogicalNotEqual:5557case SpvOpLogicalOr:5558case SpvOpLogicalAnd:5559case SpvOpLogicalNot:5560case SpvOpBitwiseOr:5561case SpvOpBitwiseXor:5562case SpvOpBitwiseAnd:5563case SpvOpIEqual:5564case SpvOpFOrdEqual:5565case SpvOpFUnordEqual:5566case SpvOpINotEqual:5567case SpvOpFOrdNotEqual:5568case SpvOpFUnordNotEqual:5569case SpvOpULessThan:5570case SpvOpSLessThan:5571case SpvOpFOrdLessThan:5572case SpvOpFUnordLessThan:5573case SpvOpUGreaterThan:5574case SpvOpSGreaterThan:5575case SpvOpFOrdGreaterThan:5576case SpvOpFUnordGreaterThan:5577case SpvOpULessThanEqual:5578case SpvOpSLessThanEqual:5579case SpvOpFOrdLessThanEqual:5580case SpvOpFUnordLessThanEqual:5581case SpvOpUGreaterThanEqual:5582case SpvOpSGreaterThanEqual:5583case SpvOpFOrdGreaterThanEqual:5584case SpvOpFUnordGreaterThanEqual:5585case SpvOpDPdx:5586case SpvOpDPdy:5587case SpvOpFwidth:5588case SpvOpDPdxFine:5589case SpvOpDPdyFine:5590case SpvOpFwidthFine:5591case SpvOpDPdxCoarse:5592case SpvOpDPdyCoarse:5593case SpvOpFwidthCoarse:5594case SpvOpBitFieldInsert:5595case SpvOpBitFieldSExtract:5596case SpvOpBitFieldUExtract:5597case SpvOpBitReverse:5598case SpvOpBitCount:5599case SpvOpTranspose:5600case SpvOpOuterProduct:5601case SpvOpMatrixTimesScalar:5602case SpvOpVectorTimesMatrix:5603case SpvOpMatrixTimesVector:5604case SpvOpMatrixTimesMatrix:5605case SpvOpUCountLeadingZerosINTEL:5606case SpvOpUCountTrailingZerosINTEL:5607case SpvOpAbsISubINTEL:5608case SpvOpAbsUSubINTEL:5609case SpvOpIAddSatINTEL:5610case SpvOpUAddSatINTEL:5611case SpvOpIAverageINTEL:5612case SpvOpUAverageINTEL:5613case SpvOpIAverageRoundedINTEL:5614case SpvOpUAverageRoundedINTEL:5615case SpvOpISubSatINTEL:5616case SpvOpUSubSatINTEL:5617case SpvOpIMul32x16INTEL:5618case SpvOpUMul32x16INTEL:5619vtn_handle_alu(b, opcode, w, count);5620break;56215622case SpvOpBitcast:5623vtn_handle_bitcast(b, w, count);5624break;56255626case SpvOpVectorExtractDynamic:5627case SpvOpVectorInsertDynamic:5628case SpvOpVectorShuffle:5629case SpvOpCompositeConstruct:5630case SpvOpCompositeExtract:5631case SpvOpCompositeInsert:5632case SpvOpCopyLogical:5633case SpvOpCopyObject:5634vtn_handle_composite(b, opcode, w, count);5635break;56365637case SpvOpEmitVertex:5638case SpvOpEndPrimitive:5639case SpvOpEmitStreamVertex:5640case SpvOpEndStreamPrimitive:5641case SpvOpControlBarrier:5642case SpvOpMemoryBarrier:5643vtn_handle_barrier(b, opcode, w, count);5644break;56455646case SpvOpGroupNonUniformElect:5647case SpvOpGroupNonUniformAll:5648case SpvOpGroupNonUniformAny:5649case SpvOpGroupNonUniformAllEqual:5650case SpvOpGroupNonUniformBroadcast:5651case SpvOpGroupNonUniformBroadcastFirst:5652case SpvOpGroupNonUniformBallot:5653case SpvOpGroupNonUniformInverseBallot:5654case SpvOpGroupNonUniformBallotBitExtract:5655case SpvOpGroupNonUniformBallotBitCount:5656case SpvOpGroupNonUniformBallotFindLSB:5657case SpvOpGroupNonUniformBallotFindMSB:5658case SpvOpGroupNonUniformShuffle:5659case SpvOpGroupNonUniformShuffleXor:5660case SpvOpGroupNonUniformShuffleUp:5661case SpvOpGroupNonUniformShuffleDown:5662case SpvOpGroupNonUniformIAdd:5663case SpvOpGroupNonUniformFAdd:5664case SpvOpGroupNonUniformIMul:5665case SpvOpGroupNonUniformFMul:5666case SpvOpGroupNonUniformSMin:5667case SpvOpGroupNonUniformUMin:5668case SpvOpGroupNonUniformFMin:5669case SpvOpGroupNonUniformSMax:5670case SpvOpGroupNonUniformUMax:5671case SpvOpGroupNonUniformFMax:5672case SpvOpGroupNonUniformBitwiseAnd:5673case SpvOpGroupNonUniformBitwiseOr:5674case SpvOpGroupNonUniformBitwiseXor:5675case SpvOpGroupNonUniformLogicalAnd:5676case SpvOpGroupNonUniformLogicalOr:5677case SpvOpGroupNonUniformLogicalXor:5678case SpvOpGroupNonUniformQuadBroadcast:5679case SpvOpGroupNonUniformQuadSwap:5680case SpvOpGroupAll:5681case SpvOpGroupAny:5682case SpvOpGroupBroadcast:5683case SpvOpGroupIAdd:5684case SpvOpGroupFAdd:5685case SpvOpGroupFMin:5686case SpvOpGroupUMin:5687case SpvOpGroupSMin:5688case SpvOpGroupFMax:5689case SpvOpGroupUMax:5690case SpvOpGroupSMax:5691case SpvOpSubgroupBallotKHR:5692case SpvOpSubgroupFirstInvocationKHR:5693case SpvOpSubgroupReadInvocationKHR:5694case SpvOpSubgroupAllKHR:5695case SpvOpSubgroupAnyKHR:5696case SpvOpSubgroupAllEqualKHR:5697case SpvOpGroupIAddNonUniformAMD:5698case SpvOpGroupFAddNonUniformAMD:5699case SpvOpGroupFMinNonUniformAMD:5700case SpvOpGroupUMinNonUniformAMD:5701case SpvOpGroupSMinNonUniformAMD:5702case SpvOpGroupFMaxNonUniformAMD:5703case SpvOpGroupUMaxNonUniformAMD:5704case SpvOpGroupSMaxNonUniformAMD:5705case SpvOpSubgroupShuffleINTEL:5706case SpvOpSubgroupShuffleDownINTEL:5707case SpvOpSubgroupShuffleUpINTEL:5708case SpvOpSubgroupShuffleXorINTEL:5709vtn_handle_subgroup(b, opcode, w, count);5710break;57115712case SpvOpPtrDiff:5713case SpvOpPtrEqual:5714case SpvOpPtrNotEqual:5715vtn_handle_ptr(b, opcode, w, count);5716break;57175718case SpvOpBeginInvocationInterlockEXT:5719nir_begin_invocation_interlock(&b->nb);5720break;57215722case SpvOpEndInvocationInterlockEXT:5723nir_end_invocation_interlock(&b->nb);5724break;57255726case SpvOpDemoteToHelperInvocationEXT: {5727nir_demote(&b->nb);5728break;5729}57305731case SpvOpIsHelperInvocationEXT: {5732vtn_push_nir_ssa(b, w[2], nir_is_helper_invocation(&b->nb, 1));5733break;5734}57355736case SpvOpReadClockKHR: {5737SpvScope scope = vtn_constant_uint(b, w[3]);5738nir_scope nir_scope;57395740switch (scope) {5741case SpvScopeDevice:5742nir_scope = NIR_SCOPE_DEVICE;5743break;5744case SpvScopeSubgroup:5745nir_scope = NIR_SCOPE_SUBGROUP;5746break;5747default:5748vtn_fail("invalid read clock scope");5749}57505751/* Operation supports two result types: uvec2 and uint64_t. The NIR5752* intrinsic gives uvec2, so pack the result for the other case.5753*/5754nir_ssa_def *result = nir_shader_clock(&b->nb, nir_scope);57555756struct vtn_type *type = vtn_get_type(b, w[1]);5757const struct glsl_type *dest_type = type->type;57585759if (glsl_type_is_vector(dest_type)) {5760assert(dest_type == glsl_vector_type(GLSL_TYPE_UINT, 2));5761} else {5762assert(glsl_type_is_scalar(dest_type));5763assert(glsl_get_base_type(dest_type) == GLSL_TYPE_UINT64);5764result = nir_pack_64_2x32(&b->nb, result);5765}57665767vtn_push_nir_ssa(b, w[2], result);5768break;5769}57705771case SpvOpTraceNV:5772case SpvOpTraceRayKHR:5773case SpvOpReportIntersectionKHR:5774case SpvOpIgnoreIntersectionNV:5775case SpvOpTerminateRayNV:5776case SpvOpExecuteCallableNV:5777case SpvOpExecuteCallableKHR:5778vtn_handle_ray_intrinsic(b, opcode, w, count);5779break;57805781case SpvOpLifetimeStart:5782case SpvOpLifetimeStop:5783break;57845785case SpvOpGroupAsyncCopy:5786case SpvOpGroupWaitEvents:5787vtn_handle_opencl_core_instruction(b, opcode, w, count);5788break;57895790default:5791vtn_fail_with_opcode("Unhandled opcode", opcode);5792}57935794return true;5795}57965797struct vtn_builder*5798vtn_create_builder(const uint32_t *words, size_t word_count,5799gl_shader_stage stage, const char *entry_point_name,5800const struct spirv_to_nir_options *options)5801{5802/* Initialize the vtn_builder object */5803struct vtn_builder *b = rzalloc(NULL, struct vtn_builder);5804struct spirv_to_nir_options *dup_options =5805ralloc(b, struct spirv_to_nir_options);5806*dup_options = *options;58075808b->spirv = words;5809b->spirv_word_count = word_count;5810b->file = NULL;5811b->line = -1;5812b->col = -1;5813list_inithead(&b->functions);5814b->entry_point_stage = stage;5815b->entry_point_name = entry_point_name;5816b->options = dup_options;58175818/*5819* Handle the SPIR-V header (first 5 dwords).5820* Can't use vtx_assert() as the setjmp(3) target isn't initialized yet.5821*/5822if (word_count <= 5)5823goto fail;58245825if (words[0] != SpvMagicNumber) {5826vtn_err("words[0] was 0x%x, want 0x%x", words[0], SpvMagicNumber);5827goto fail;5828}58295830b->version = words[1];5831if (b->version < 0x10000) {5832vtn_err("version was 0x%x, want >= 0x10000", b->version);5833goto fail;5834}58355836b->generator_id = words[2] >> 16;5837uint16_t generator_version = words[2];58385839/* In GLSLang commit 8297936dd6eb3, their handling of barrier() was fixed5840* to provide correct memory semantics on compute shader barrier()5841* commands. Prior to that, we need to fix them up ourselves. This5842* GLSLang fix caused them to bump to generator version 3.5843*/5844b->wa_glslang_cs_barrier =5845(b->generator_id == vtn_generator_glslang_reference_front_end &&5846generator_version < 3);58475848/* words[2] == generator magic */5849unsigned value_id_bound = words[3];5850if (words[4] != 0) {5851vtn_err("words[4] was %u, want 0", words[4]);5852goto fail;5853}58545855b->value_id_bound = value_id_bound;5856b->values = rzalloc_array(b, struct vtn_value, value_id_bound);58575858if (b->options->environment == NIR_SPIRV_VULKAN && b->version < 0x10400)5859b->vars_used_indirectly = _mesa_pointer_set_create(b);58605861return b;5862fail:5863ralloc_free(b);5864return NULL;5865}58665867static nir_function *5868vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,5869nir_function *entry_point)5870{5871vtn_assert(entry_point == b->entry_point->func->nir_func);5872vtn_fail_if(!entry_point->name, "entry points are required to have a name");5873const char *func_name =5874ralloc_asprintf(b->shader, "__wrapped_%s", entry_point->name);58755876vtn_assert(b->shader->info.stage == MESA_SHADER_KERNEL);58775878nir_function *main_entry_point = nir_function_create(b->shader, func_name);5879main_entry_point->impl = nir_function_impl_create(main_entry_point);5880nir_builder_init(&b->nb, main_entry_point->impl);5881b->nb.cursor = nir_after_cf_list(&main_entry_point->impl->body);5882b->func_param_idx = 0;58835884nir_call_instr *call = nir_call_instr_create(b->nb.shader, entry_point);58855886for (unsigned i = 0; i < entry_point->num_params; ++i) {5887struct vtn_type *param_type = b->entry_point->func->type->params[i];58885889/* consider all pointers to function memory to be parameters passed5890* by value5891*/5892bool is_by_val = param_type->base_type == vtn_base_type_pointer &&5893param_type->storage_class == SpvStorageClassFunction;58945895/* input variable */5896nir_variable *in_var = rzalloc(b->nb.shader, nir_variable);5897in_var->data.mode = nir_var_uniform;5898in_var->data.read_only = true;5899in_var->data.location = i;5900if (param_type->base_type == vtn_base_type_image) {5901in_var->data.access =5902spirv_to_gl_access_qualifier(b, param_type->access_qualifier);5903}59045905if (is_by_val)5906in_var->type = param_type->deref->type;5907else if (param_type->base_type == vtn_base_type_image)5908in_var->type = param_type->glsl_image;5909else if (param_type->base_type == vtn_base_type_sampler)5910in_var->type = glsl_bare_sampler_type();5911else5912in_var->type = param_type->type;59135914nir_shader_add_variable(b->nb.shader, in_var);59155916/* we have to copy the entire variable into function memory */5917if (is_by_val) {5918nir_variable *copy_var =5919nir_local_variable_create(main_entry_point->impl, in_var->type,5920"copy_in");5921nir_copy_var(&b->nb, copy_var, in_var);5922call->params[i] =5923nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->dest.ssa);5924} else if (param_type->base_type == vtn_base_type_image ||5925param_type->base_type == vtn_base_type_sampler) {5926/* Don't load the var, just pass a deref of it */5927call->params[i] = nir_src_for_ssa(&nir_build_deref_var(&b->nb, in_var)->dest.ssa);5928} else {5929call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var));5930}5931}59325933nir_builder_instr_insert(&b->nb, &call->instr);59345935return main_entry_point;5936}59375938static bool5939can_remove(nir_variable *var, void *data)5940{5941const struct set *vars_used_indirectly = data;5942return !_mesa_set_search(vars_used_indirectly, var);5943}59445945nir_shader *5946spirv_to_nir(const uint32_t *words, size_t word_count,5947struct nir_spirv_specialization *spec, unsigned num_spec,5948gl_shader_stage stage, const char *entry_point_name,5949const struct spirv_to_nir_options *options,5950const nir_shader_compiler_options *nir_options)59515952{5953const uint32_t *word_end = words + word_count;59545955struct vtn_builder *b = vtn_create_builder(words, word_count,5956stage, entry_point_name,5957options);59585959if (b == NULL)5960return NULL;59615962/* See also _vtn_fail() */5963if (vtn_setjmp(b->fail_jump)) {5964ralloc_free(b);5965return NULL;5966}59675968/* Skip the SPIR-V header, handled at vtn_create_builder */5969words+= 5;59705971b->shader = nir_shader_create(b, stage, nir_options, NULL);5972b->shader->info.float_controls_execution_mode = options->float_controls_execution_mode;59735974/* Handle all the preamble instructions */5975words = vtn_foreach_instruction(b, words, word_end,5976vtn_handle_preamble_instruction);59775978/* DirectXShaderCompiler and glslang/shaderc both create OpKill from HLSL's5979* discard/clip, which uses demote semantics. DirectXShaderCompiler will use5980* demote if the extension is enabled, so we disable this workaround in that5981* case.5982*5983* Related glslang issue: https://github.com/KhronosGroup/glslang/issues/24165984*/5985bool glslang = b->generator_id == vtn_generator_glslang_reference_front_end ||5986b->generator_id == vtn_generator_shaderc_over_glslang;5987bool dxsc = b->generator_id == vtn_generator_spiregg;5988b->convert_discard_to_demote = ((dxsc && !b->uses_demote_to_helper_invocation) ||5989(glslang && b->source_lang == SpvSourceLanguageHLSL)) &&5990options->caps.demote_to_helper_invocation;59915992if (!options->create_library && b->entry_point == NULL) {5993vtn_fail("Entry point not found for %s shader \"%s\"",5994_mesa_shader_stage_to_string(stage), entry_point_name);5995ralloc_free(b);5996return NULL;5997}59985999/* Ensure a sane address mode is being used for function temps */6000assert(nir_address_format_bit_size(b->options->temp_addr_format) == nir_get_ptr_bitsize(b->shader));6001assert(nir_address_format_num_components(b->options->temp_addr_format) == 1);60026003/* Set shader info defaults */6004if (stage == MESA_SHADER_GEOMETRY)6005b->shader->info.gs.invocations = 1;60066007/* Parse execution modes. */6008if (!options->create_library)6009vtn_foreach_execution_mode(b, b->entry_point,6010vtn_handle_execution_mode, NULL);60116012b->specializations = spec;6013b->num_specializations = num_spec;60146015/* Handle all variable, type, and constant instructions */6016words = vtn_foreach_instruction(b, words, word_end,6017vtn_handle_variable_or_type_instruction);60186019/* Parse execution modes that depend on IDs. Must happen after we have6020* constants parsed.6021*/6022if (!options->create_library)6023vtn_foreach_execution_mode(b, b->entry_point,6024vtn_handle_execution_mode_id, NULL);60256026if (b->workgroup_size_builtin) {6027vtn_assert(gl_shader_stage_uses_workgroup(stage));6028vtn_assert(b->workgroup_size_builtin->type->type ==6029glsl_vector_type(GLSL_TYPE_UINT, 3));60306031nir_const_value *const_size =6032b->workgroup_size_builtin->constant->values;60336034b->shader->info.workgroup_size[0] = const_size[0].u32;6035b->shader->info.workgroup_size[1] = const_size[1].u32;6036b->shader->info.workgroup_size[2] = const_size[2].u32;6037}60386039/* Set types on all vtn_values */6040vtn_foreach_instruction(b, words, word_end, vtn_set_instruction_result_type);60416042vtn_build_cfg(b, words, word_end);60436044if (!options->create_library) {6045assert(b->entry_point->value_type == vtn_value_type_function);6046b->entry_point->func->referenced = true;6047}60486049bool progress;6050do {6051progress = false;6052vtn_foreach_cf_node(node, &b->functions) {6053struct vtn_function *func = vtn_cf_node_as_function(node);6054if ((options->create_library || func->referenced) && !func->emitted) {6055b->const_table = _mesa_pointer_hash_table_create(b);60566057vtn_function_emit(b, func, vtn_handle_body_instruction);6058progress = true;6059}6060}6061} while (progress);60626063if (!options->create_library) {6064vtn_assert(b->entry_point->value_type == vtn_value_type_function);6065nir_function *entry_point = b->entry_point->func->nir_func;6066vtn_assert(entry_point);60676068/* post process entry_points with input params */6069if (entry_point->num_params && b->shader->info.stage == MESA_SHADER_KERNEL)6070entry_point = vtn_emit_kernel_entry_point_wrapper(b, entry_point);60716072entry_point->is_entrypoint = true;6073}60746075/* structurize the CFG */6076nir_lower_goto_ifs(b->shader);60776078/* A SPIR-V module can have multiple shaders stages and also multiple6079* shaders of the same stage. Global variables are declared per-module.6080*6081* Starting in SPIR-V 1.4 the list of global variables is part of6082* OpEntryPoint, so only valid ones will be created. Previous versions6083* only have Input and Output variables listed, so remove dead variables to6084* clean up the remaining ones.6085*/6086if (!options->create_library && b->version < 0x10400) {6087const nir_remove_dead_variables_options dead_opts = {6088.can_remove_var = can_remove,6089.can_remove_var_data = b->vars_used_indirectly,6090};6091nir_remove_dead_variables(b->shader, ~(nir_var_function_temp |6092nir_var_shader_out |6093nir_var_shader_in |6094nir_var_system_value),6095b->vars_used_indirectly ? &dead_opts : NULL);6096}60976098nir_foreach_variable_in_shader(var, b->shader) {6099switch (var->data.mode) {6100case nir_var_mem_ubo:6101b->shader->info.num_ubos++;6102break;6103case nir_var_mem_ssbo:6104b->shader->info.num_ssbos++;6105break;6106case nir_var_mem_push_const:6107vtn_assert(b->shader->num_uniforms == 0);6108b->shader->num_uniforms =6109glsl_get_explicit_size(glsl_without_array(var->type), false);6110break;6111}6112}61136114/* We sometimes generate bogus derefs that, while never used, give the6115* validator a bit of heartburn. Run dead code to get rid of them.6116*/6117nir_opt_dce(b->shader);61186119/* Per SPV_KHR_workgroup_storage_explicit_layout, if one shared variable is6120* a Block, all of them will be and Blocks are explicitly laid out.6121*/6122nir_foreach_variable_with_modes(var, b->shader, nir_var_mem_shared) {6123if (glsl_type_is_interface(var->type)) {6124assert(b->options->caps.workgroup_memory_explicit_layout);6125b->shader->info.shared_memory_explicit_layout = true;6126break;6127}6128}6129if (b->shader->info.shared_memory_explicit_layout) {6130unsigned size = 0;6131nir_foreach_variable_with_modes(var, b->shader, nir_var_mem_shared) {6132assert(glsl_type_is_interface(var->type));6133const bool align_to_stride = false;6134size = MAX2(size, glsl_get_explicit_size(var->type, align_to_stride));6135}6136b->shader->info.shared_size = size;6137}61386139/* Unparent the shader from the vtn_builder before we delete the builder */6140ralloc_steal(NULL, b->shader);61416142nir_shader *shader = b->shader;6143ralloc_free(b);61446145return shader;6146}614761486149