Path: blob/21.2-virgl/src/compiler/spirv/vtn_variables.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 "spirv_info.h"29#include "nir_deref.h"30#include <vulkan/vulkan_core.h>3132static struct vtn_pointer*33vtn_align_pointer(struct vtn_builder *b, struct vtn_pointer *ptr,34unsigned alignment)35{36if (alignment == 0)37return ptr;3839if (!util_is_power_of_two_nonzero(alignment)) {40vtn_warn("Provided alignment is not a power of two");41alignment = 1 << (ffs(alignment) - 1);42}4344/* If this pointer doesn't have a deref, bail. This either means we're45* using the old offset+alignment pointers which don't support carrying46* alignment information or we're a pointer that is below the block47* boundary in our access chain in which case alignment is meaningless.48*/49if (ptr->deref == NULL)50return ptr;5152/* Ignore alignment information on logical pointers. This way, we don't53* trip up drivers with unnecessary casts.54*/55nir_address_format addr_format = vtn_mode_to_address_format(b, ptr->mode);56if (addr_format == nir_address_format_logical)57return ptr;5859struct vtn_pointer *copy = ralloc(b, struct vtn_pointer);60*copy = *ptr;61copy->deref = nir_alignment_deref_cast(&b->nb, ptr->deref, alignment, 0);6263return copy;64}6566static void67ptr_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,68const struct vtn_decoration *dec, void *void_ptr)69{70struct vtn_pointer *ptr = void_ptr;7172switch (dec->decoration) {73case SpvDecorationNonUniformEXT:74ptr->access |= ACCESS_NON_UNIFORM;75break;7677default:78break;79}80}8182struct access_align {83enum gl_access_qualifier access;84uint32_t alignment;85};8687static void88access_align_cb(struct vtn_builder *b, struct vtn_value *val, int member,89const struct vtn_decoration *dec, void *void_ptr)90{91struct access_align *aa = void_ptr;9293switch (dec->decoration) {94case SpvDecorationAlignment:95aa->alignment = dec->operands[0];96break;9798case SpvDecorationNonUniformEXT:99aa->access |= ACCESS_NON_UNIFORM;100break;101102default:103break;104}105}106107static struct vtn_pointer*108vtn_decorate_pointer(struct vtn_builder *b, struct vtn_value *val,109struct vtn_pointer *ptr)110{111struct access_align aa = { 0, };112vtn_foreach_decoration(b, val, access_align_cb, &aa);113114ptr = vtn_align_pointer(b, ptr, aa.alignment);115116/* If we're adding access flags, make a copy of the pointer. We could117* probably just OR them in without doing so but this prevents us from118* leaking them any further than actually specified in the SPIR-V.119*/120if (aa.access & ~ptr->access) {121struct vtn_pointer *copy = ralloc(b, struct vtn_pointer);122*copy = *ptr;123copy->access |= aa.access;124return copy;125}126127return ptr;128}129130struct vtn_value *131vtn_push_pointer(struct vtn_builder *b, uint32_t value_id,132struct vtn_pointer *ptr)133{134struct vtn_value *val = vtn_push_value(b, value_id, vtn_value_type_pointer);135val->pointer = vtn_decorate_pointer(b, val, ptr);136return val;137}138139void140vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,141uint32_t dst_value_id)142{143struct vtn_value *src = vtn_untyped_value(b, src_value_id);144struct vtn_value *dst = vtn_untyped_value(b, dst_value_id);145struct vtn_value src_copy = *src;146147vtn_fail_if(dst->value_type != vtn_value_type_invalid,148"SPIR-V id %u has already been written by another instruction",149dst_value_id);150151vtn_fail_if(dst->type->id != src->type->id,152"Result Type must equal Operand type");153154src_copy.name = dst->name;155src_copy.decoration = dst->decoration;156src_copy.type = dst->type;157*dst = src_copy;158159if (dst->value_type == vtn_value_type_pointer)160dst->pointer = vtn_decorate_pointer(b, dst, dst->pointer);161}162163static struct vtn_access_chain *164vtn_access_chain_create(struct vtn_builder *b, unsigned length)165{166struct vtn_access_chain *chain;167168/* Subtract 1 from the length since there's already one built in */169size_t size = sizeof(*chain) +170(MAX2(length, 1) - 1) * sizeof(chain->link[0]);171chain = rzalloc_size(b, size);172chain->length = length;173174return chain;175}176177static bool178vtn_mode_is_cross_invocation(struct vtn_builder *b,179enum vtn_variable_mode mode)180{181return mode == vtn_variable_mode_ssbo ||182mode == vtn_variable_mode_ubo ||183mode == vtn_variable_mode_phys_ssbo ||184mode == vtn_variable_mode_push_constant ||185mode == vtn_variable_mode_workgroup ||186mode == vtn_variable_mode_cross_workgroup;187}188189static bool190vtn_pointer_is_external_block(struct vtn_builder *b,191struct vtn_pointer *ptr)192{193return ptr->mode == vtn_variable_mode_ssbo ||194ptr->mode == vtn_variable_mode_ubo ||195ptr->mode == vtn_variable_mode_phys_ssbo;196}197198static nir_ssa_def *199vtn_access_link_as_ssa(struct vtn_builder *b, struct vtn_access_link link,200unsigned stride, unsigned bit_size)201{202vtn_assert(stride > 0);203if (link.mode == vtn_access_mode_literal) {204return nir_imm_intN_t(&b->nb, link.id * stride, bit_size);205} else {206nir_ssa_def *ssa = vtn_ssa_value(b, link.id)->def;207if (ssa->bit_size != bit_size)208ssa = nir_i2i(&b->nb, ssa, bit_size);209return nir_imul_imm(&b->nb, ssa, stride);210}211}212213static VkDescriptorType214vk_desc_type_for_mode(struct vtn_builder *b, enum vtn_variable_mode mode)215{216switch (mode) {217case vtn_variable_mode_ubo:218return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;219case vtn_variable_mode_ssbo:220return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;221case vtn_variable_mode_accel_struct:222return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;223default:224vtn_fail("Invalid mode for vulkan_resource_index");225}226}227228static nir_ssa_def *229vtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var,230nir_ssa_def *desc_array_index)231{232vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);233234if (!desc_array_index)235desc_array_index = nir_imm_int(&b->nb, 0);236237if (b->vars_used_indirectly) {238vtn_assert(var->var);239_mesa_set_add(b->vars_used_indirectly, var->var);240}241242nir_intrinsic_instr *instr =243nir_intrinsic_instr_create(b->nb.shader,244nir_intrinsic_vulkan_resource_index);245instr->src[0] = nir_src_for_ssa(desc_array_index);246nir_intrinsic_set_desc_set(instr, var->descriptor_set);247nir_intrinsic_set_binding(instr, var->binding);248nir_intrinsic_set_desc_type(instr, vk_desc_type_for_mode(b, var->mode));249250nir_address_format addr_format = vtn_mode_to_address_format(b, var->mode);251nir_ssa_dest_init(&instr->instr, &instr->dest,252nir_address_format_num_components(addr_format),253nir_address_format_bit_size(addr_format), NULL);254instr->num_components = instr->dest.ssa.num_components;255nir_builder_instr_insert(&b->nb, &instr->instr);256257return &instr->dest.ssa;258}259260static nir_ssa_def *261vtn_resource_reindex(struct vtn_builder *b, enum vtn_variable_mode mode,262nir_ssa_def *base_index, nir_ssa_def *offset_index)263{264vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);265266nir_intrinsic_instr *instr =267nir_intrinsic_instr_create(b->nb.shader,268nir_intrinsic_vulkan_resource_reindex);269instr->src[0] = nir_src_for_ssa(base_index);270instr->src[1] = nir_src_for_ssa(offset_index);271nir_intrinsic_set_desc_type(instr, vk_desc_type_for_mode(b, mode));272273nir_address_format addr_format = vtn_mode_to_address_format(b, mode);274nir_ssa_dest_init(&instr->instr, &instr->dest,275nir_address_format_num_components(addr_format),276nir_address_format_bit_size(addr_format), NULL);277instr->num_components = instr->dest.ssa.num_components;278nir_builder_instr_insert(&b->nb, &instr->instr);279280return &instr->dest.ssa;281}282283static nir_ssa_def *284vtn_descriptor_load(struct vtn_builder *b, enum vtn_variable_mode mode,285nir_ssa_def *desc_index)286{287vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);288289nir_intrinsic_instr *desc_load =290nir_intrinsic_instr_create(b->nb.shader,291nir_intrinsic_load_vulkan_descriptor);292desc_load->src[0] = nir_src_for_ssa(desc_index);293nir_intrinsic_set_desc_type(desc_load, vk_desc_type_for_mode(b, mode));294295nir_address_format addr_format = vtn_mode_to_address_format(b, mode);296nir_ssa_dest_init(&desc_load->instr, &desc_load->dest,297nir_address_format_num_components(addr_format),298nir_address_format_bit_size(addr_format), NULL);299desc_load->num_components = desc_load->dest.ssa.num_components;300nir_builder_instr_insert(&b->nb, &desc_load->instr);301302return &desc_load->dest.ssa;303}304305static struct vtn_pointer *306vtn_pointer_dereference(struct vtn_builder *b,307struct vtn_pointer *base,308struct vtn_access_chain *deref_chain)309{310struct vtn_type *type = base->type;311enum gl_access_qualifier access = base->access | deref_chain->access;312unsigned idx = 0;313314nir_deref_instr *tail;315if (base->deref) {316tail = base->deref;317} else if (b->options->environment == NIR_SPIRV_VULKAN &&318(vtn_pointer_is_external_block(b, base) ||319base->mode == vtn_variable_mode_accel_struct)) {320nir_ssa_def *block_index = base->block_index;321322/* We dereferencing an external block pointer. Correctness of this323* operation relies on one particular line in the SPIR-V spec, section324* entitled "Validation Rules for Shader Capabilities":325*326* "Block and BufferBlock decorations cannot decorate a structure327* type that is nested at any level inside another structure type328* decorated with Block or BufferBlock."329*330* This means that we can detect the point where we cross over from331* descriptor indexing to buffer indexing by looking for the block332* decorated struct type. Anything before the block decorated struct333* type is a descriptor indexing operation and anything after the block334* decorated struct is a buffer offset operation.335*/336337/* Figure out the descriptor array index if any338*339* Some of the Vulkan CTS tests with hand-rolled SPIR-V have been known340* to forget the Block or BufferBlock decoration from time to time.341* It's more robust if we check for both !block_index and for the type342* to contain a block. This way there's a decent chance that arrays of343* UBOs/SSBOs will work correctly even if variable pointers are344* completley toast.345*/346nir_ssa_def *desc_arr_idx = NULL;347if (!block_index || vtn_type_contains_block(b, type) ||348base->mode == vtn_variable_mode_accel_struct) {349/* If our type contains a block, then we're still outside the block350* and we need to process enough levels of dereferences to get inside351* of it. Same applies to acceleration structures.352*/353if (deref_chain->ptr_as_array) {354unsigned aoa_size = glsl_get_aoa_size(type->type);355desc_arr_idx = vtn_access_link_as_ssa(b, deref_chain->link[idx],356MAX2(aoa_size, 1), 32);357idx++;358}359360for (; idx < deref_chain->length; idx++) {361if (type->base_type != vtn_base_type_array) {362vtn_assert(type->base_type == vtn_base_type_struct);363break;364}365366unsigned aoa_size = glsl_get_aoa_size(type->array_element->type);367nir_ssa_def *arr_offset =368vtn_access_link_as_ssa(b, deref_chain->link[idx],369MAX2(aoa_size, 1), 32);370if (desc_arr_idx)371desc_arr_idx = nir_iadd(&b->nb, desc_arr_idx, arr_offset);372else373desc_arr_idx = arr_offset;374375type = type->array_element;376access |= type->access;377}378}379380if (!block_index) {381vtn_assert(base->var && base->type);382block_index = vtn_variable_resource_index(b, base->var, desc_arr_idx);383} else if (desc_arr_idx) {384block_index = vtn_resource_reindex(b, base->mode,385block_index, desc_arr_idx);386}387388if (idx == deref_chain->length) {389/* The entire deref was consumed in finding the block index. Return390* a pointer which just has a block index and a later access chain391* will dereference deeper.392*/393struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);394ptr->mode = base->mode;395ptr->type = type;396ptr->block_index = block_index;397ptr->access = access;398return ptr;399}400401/* If we got here, there's more access chain to handle and we have the402* final block index. Insert a descriptor load and cast to a deref to403* start the deref chain.404*/405nir_ssa_def *desc = vtn_descriptor_load(b, base->mode, block_index);406407assert(base->mode == vtn_variable_mode_ssbo ||408base->mode == vtn_variable_mode_ubo);409nir_variable_mode nir_mode =410base->mode == vtn_variable_mode_ssbo ? nir_var_mem_ssbo : nir_var_mem_ubo;411412tail = nir_build_deref_cast(&b->nb, desc, nir_mode,413vtn_type_get_nir_type(b, type, base->mode),414base->ptr_type->stride);415} else if (base->mode == vtn_variable_mode_shader_record) {416/* For ShaderRecordBufferKHR variables, we don't have a nir_variable.417* It's just a fancy handle around a pointer to the shader record for418* the current shader.419*/420tail = nir_build_deref_cast(&b->nb, nir_load_shader_record_ptr(&b->nb),421nir_var_mem_constant,422vtn_type_get_nir_type(b, base->type,423base->mode),4240 /* ptr_as_array stride */);425} else {426assert(base->var && base->var->var);427tail = nir_build_deref_var(&b->nb, base->var->var);428if (base->ptr_type && base->ptr_type->type) {429tail->dest.ssa.num_components =430glsl_get_vector_elements(base->ptr_type->type);431tail->dest.ssa.bit_size = glsl_get_bit_size(base->ptr_type->type);432}433}434435if (idx == 0 && deref_chain->ptr_as_array) {436/* We start with a deref cast to get the stride. Hopefully, we'll be437* able to delete that cast eventually.438*/439tail = nir_build_deref_cast(&b->nb, &tail->dest.ssa, tail->modes,440tail->type, base->ptr_type->stride);441442nir_ssa_def *index = vtn_access_link_as_ssa(b, deref_chain->link[0], 1,443tail->dest.ssa.bit_size);444tail = nir_build_deref_ptr_as_array(&b->nb, tail, index);445idx++;446}447448for (; idx < deref_chain->length; idx++) {449if (glsl_type_is_struct_or_ifc(type->type)) {450vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal);451unsigned field = deref_chain->link[idx].id;452tail = nir_build_deref_struct(&b->nb, tail, field);453type = type->members[field];454} else {455nir_ssa_def *arr_index =456vtn_access_link_as_ssa(b, deref_chain->link[idx], 1,457tail->dest.ssa.bit_size);458tail = nir_build_deref_array(&b->nb, tail, arr_index);459type = type->array_element;460}461462access |= type->access;463}464465struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);466ptr->mode = base->mode;467ptr->type = type;468ptr->var = base->var;469ptr->deref = tail;470ptr->access = access;471472return ptr;473}474475nir_deref_instr *476vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr)477{478if (!ptr->deref) {479struct vtn_access_chain chain = {480.length = 0,481};482ptr = vtn_pointer_dereference(b, ptr, &chain);483}484485return ptr->deref;486}487488static void489_vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_instr *deref,490struct vtn_ssa_value *inout,491enum gl_access_qualifier access)492{493if (glsl_type_is_vector_or_scalar(deref->type)) {494if (load) {495inout->def = nir_load_deref_with_access(&b->nb, deref, access);496} else {497nir_store_deref_with_access(&b->nb, deref, inout->def, ~0, access);498}499} else if (glsl_type_is_array(deref->type) ||500glsl_type_is_matrix(deref->type)) {501unsigned elems = glsl_get_length(deref->type);502for (unsigned i = 0; i < elems; i++) {503nir_deref_instr *child =504nir_build_deref_array_imm(&b->nb, deref, i);505_vtn_local_load_store(b, load, child, inout->elems[i], access);506}507} else {508vtn_assert(glsl_type_is_struct_or_ifc(deref->type));509unsigned elems = glsl_get_length(deref->type);510for (unsigned i = 0; i < elems; i++) {511nir_deref_instr *child = nir_build_deref_struct(&b->nb, deref, i);512_vtn_local_load_store(b, load, child, inout->elems[i], access);513}514}515}516517nir_deref_instr *518vtn_nir_deref(struct vtn_builder *b, uint32_t id)519{520struct vtn_pointer *ptr = vtn_value(b, id, vtn_value_type_pointer)->pointer;521return vtn_pointer_to_deref(b, ptr);522}523524/*525* Gets the NIR-level deref tail, which may have as a child an array deref526* selecting which component due to OpAccessChain supporting per-component527* indexing in SPIR-V.528*/529static nir_deref_instr *530get_deref_tail(nir_deref_instr *deref)531{532if (deref->deref_type != nir_deref_type_array)533return deref;534535nir_deref_instr *parent =536nir_instr_as_deref(deref->parent.ssa->parent_instr);537538if (glsl_type_is_vector(parent->type))539return parent;540else541return deref;542}543544struct vtn_ssa_value *545vtn_local_load(struct vtn_builder *b, nir_deref_instr *src,546enum gl_access_qualifier access)547{548nir_deref_instr *src_tail = get_deref_tail(src);549struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type);550_vtn_local_load_store(b, true, src_tail, val, access);551552if (src_tail != src) {553val->type = src->type;554val->def = nir_vector_extract(&b->nb, val->def, src->arr.index.ssa);555}556557return val;558}559560void561vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,562nir_deref_instr *dest, enum gl_access_qualifier access)563{564nir_deref_instr *dest_tail = get_deref_tail(dest);565566if (dest_tail != dest) {567struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);568_vtn_local_load_store(b, true, dest_tail, val, access);569570val->def = nir_vector_insert(&b->nb, val->def, src->def,571dest->arr.index.ssa);572_vtn_local_load_store(b, false, dest_tail, val, access);573} else {574_vtn_local_load_store(b, false, dest_tail, src, access);575}576}577578static nir_ssa_def *579vtn_pointer_to_descriptor(struct vtn_builder *b, struct vtn_pointer *ptr)580{581assert(ptr->mode == vtn_variable_mode_accel_struct);582if (!ptr->block_index) {583struct vtn_access_chain chain = {584.length = 0,585};586ptr = vtn_pointer_dereference(b, ptr, &chain);587}588589vtn_assert(ptr->deref == NULL && ptr->block_index != NULL);590return vtn_descriptor_load(b, ptr->mode, ptr->block_index);591}592593static void594_vtn_variable_load_store(struct vtn_builder *b, bool load,595struct vtn_pointer *ptr,596enum gl_access_qualifier access,597struct vtn_ssa_value **inout)598{599if (ptr->mode == vtn_variable_mode_uniform) {600if (ptr->type->base_type == vtn_base_type_image ||601ptr->type->base_type == vtn_base_type_sampler) {602/* See also our handling of OpTypeSampler and OpTypeImage */603vtn_assert(load);604(*inout)->def = vtn_pointer_to_ssa(b, ptr);605return;606} else if (ptr->type->base_type == vtn_base_type_sampled_image) {607/* See also our handling of OpTypeSampledImage */608vtn_assert(load);609struct vtn_sampled_image si = {610.image = vtn_pointer_to_deref(b, ptr),611.sampler = vtn_pointer_to_deref(b, ptr),612};613(*inout)->def = vtn_sampled_image_to_nir_ssa(b, si);614return;615}616} else if (ptr->mode == vtn_variable_mode_accel_struct) {617vtn_assert(load);618(*inout)->def = vtn_pointer_to_descriptor(b, ptr);619return;620}621622enum glsl_base_type base_type = glsl_get_base_type(ptr->type->type);623switch (base_type) {624case GLSL_TYPE_UINT:625case GLSL_TYPE_INT:626case GLSL_TYPE_UINT16:627case GLSL_TYPE_INT16:628case GLSL_TYPE_UINT8:629case GLSL_TYPE_INT8:630case GLSL_TYPE_UINT64:631case GLSL_TYPE_INT64:632case GLSL_TYPE_FLOAT:633case GLSL_TYPE_FLOAT16:634case GLSL_TYPE_BOOL:635case GLSL_TYPE_DOUBLE:636if (glsl_type_is_vector_or_scalar(ptr->type->type)) {637/* We hit a vector or scalar; go ahead and emit the load[s] */638nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr);639if (vtn_mode_is_cross_invocation(b, ptr->mode)) {640/* If it's cross-invocation, we call nir_load/store_deref641* directly. The vtn_local_load/store helpers are too clever and642* do magic to avoid array derefs of vectors. That magic is both643* less efficient than the direct load/store and, in the case of644* stores, is broken because it creates a race condition if two645* threads are writing to different components of the same vector646* due to the load+insert+store it uses to emulate the array647* deref.648*/649if (load) {650(*inout)->def = nir_load_deref_with_access(&b->nb, deref,651ptr->type->access | access);652} else {653nir_store_deref_with_access(&b->nb, deref, (*inout)->def, ~0,654ptr->type->access | access);655}656} else {657if (load) {658*inout = vtn_local_load(b, deref, ptr->type->access | access);659} else {660vtn_local_store(b, *inout, deref, ptr->type->access | access);661}662}663return;664}665FALLTHROUGH;666667case GLSL_TYPE_INTERFACE:668case GLSL_TYPE_ARRAY:669case GLSL_TYPE_STRUCT: {670unsigned elems = glsl_get_length(ptr->type->type);671struct vtn_access_chain chain = {672.length = 1,673.link = {674{ .mode = vtn_access_mode_literal, },675}676};677for (unsigned i = 0; i < elems; i++) {678chain.link[0].id = i;679struct vtn_pointer *elem = vtn_pointer_dereference(b, ptr, &chain);680_vtn_variable_load_store(b, load, elem, ptr->type->access | access,681&(*inout)->elems[i]);682}683return;684}685686default:687vtn_fail("Invalid access chain type");688}689}690691struct vtn_ssa_value *692vtn_variable_load(struct vtn_builder *b, struct vtn_pointer *src,693enum gl_access_qualifier access)694{695struct vtn_ssa_value *val = vtn_create_ssa_value(b, src->type->type);696_vtn_variable_load_store(b, true, src, src->access | access, &val);697return val;698}699700void701vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,702struct vtn_pointer *dest, enum gl_access_qualifier access)703{704_vtn_variable_load_store(b, false, dest, dest->access | access, &src);705}706707static void708_vtn_variable_copy(struct vtn_builder *b, struct vtn_pointer *dest,709struct vtn_pointer *src, enum gl_access_qualifier dest_access,710enum gl_access_qualifier src_access)711{712vtn_assert(glsl_get_bare_type(src->type->type) ==713glsl_get_bare_type(dest->type->type));714enum glsl_base_type base_type = glsl_get_base_type(src->type->type);715switch (base_type) {716case GLSL_TYPE_UINT:717case GLSL_TYPE_INT:718case GLSL_TYPE_UINT16:719case GLSL_TYPE_INT16:720case GLSL_TYPE_UINT8:721case GLSL_TYPE_INT8:722case GLSL_TYPE_UINT64:723case GLSL_TYPE_INT64:724case GLSL_TYPE_FLOAT:725case GLSL_TYPE_FLOAT16:726case GLSL_TYPE_DOUBLE:727case GLSL_TYPE_BOOL:728/* At this point, we have a scalar, vector, or matrix so we know that729* there cannot be any structure splitting still in the way. By730* stopping at the matrix level rather than the vector level, we731* ensure that matrices get loaded in the optimal way even if they732* are storred row-major in a UBO.733*/734vtn_variable_store(b, vtn_variable_load(b, src, src_access), dest, dest_access);735return;736737case GLSL_TYPE_INTERFACE:738case GLSL_TYPE_ARRAY:739case GLSL_TYPE_STRUCT: {740struct vtn_access_chain chain = {741.length = 1,742.link = {743{ .mode = vtn_access_mode_literal, },744}745};746unsigned elems = glsl_get_length(src->type->type);747for (unsigned i = 0; i < elems; i++) {748chain.link[0].id = i;749struct vtn_pointer *src_elem =750vtn_pointer_dereference(b, src, &chain);751struct vtn_pointer *dest_elem =752vtn_pointer_dereference(b, dest, &chain);753754_vtn_variable_copy(b, dest_elem, src_elem, dest_access, src_access);755}756return;757}758759default:760vtn_fail("Invalid access chain type");761}762}763764static void765vtn_variable_copy(struct vtn_builder *b, struct vtn_pointer *dest,766struct vtn_pointer *src, enum gl_access_qualifier dest_access,767enum gl_access_qualifier src_access)768{769/* TODO: At some point, we should add a special-case for when we can770* just emit a copy_var intrinsic.771*/772_vtn_variable_copy(b, dest, src, dest_access, src_access);773}774775static void776set_mode_system_value(struct vtn_builder *b, nir_variable_mode *mode)777{778vtn_assert(*mode == nir_var_system_value || *mode == nir_var_shader_in);779*mode = nir_var_system_value;780}781782static void783vtn_get_builtin_location(struct vtn_builder *b,784SpvBuiltIn builtin, int *location,785nir_variable_mode *mode)786{787switch (builtin) {788case SpvBuiltInPosition:789*location = VARYING_SLOT_POS;790break;791case SpvBuiltInPointSize:792*location = VARYING_SLOT_PSIZ;793break;794case SpvBuiltInClipDistance:795*location = VARYING_SLOT_CLIP_DIST0; /* XXX CLIP_DIST1? */796break;797case SpvBuiltInCullDistance:798*location = VARYING_SLOT_CULL_DIST0;799break;800case SpvBuiltInVertexId:801case SpvBuiltInVertexIndex:802/* The Vulkan spec defines VertexIndex to be non-zero-based and doesn't803* allow VertexId. The ARB_gl_spirv spec defines VertexId to be the804* same as gl_VertexID, which is non-zero-based, and removes805* VertexIndex. Since they're both defined to be non-zero-based, we use806* SYSTEM_VALUE_VERTEX_ID for both.807*/808*location = SYSTEM_VALUE_VERTEX_ID;809set_mode_system_value(b, mode);810break;811case SpvBuiltInInstanceIndex:812*location = SYSTEM_VALUE_INSTANCE_INDEX;813set_mode_system_value(b, mode);814break;815case SpvBuiltInInstanceId:816*location = SYSTEM_VALUE_INSTANCE_ID;817set_mode_system_value(b, mode);818break;819case SpvBuiltInPrimitiveId:820if (b->shader->info.stage == MESA_SHADER_FRAGMENT) {821vtn_assert(*mode == nir_var_shader_in);822*location = VARYING_SLOT_PRIMITIVE_ID;823} else if (*mode == nir_var_shader_out) {824*location = VARYING_SLOT_PRIMITIVE_ID;825} else {826*location = SYSTEM_VALUE_PRIMITIVE_ID;827set_mode_system_value(b, mode);828}829break;830case SpvBuiltInInvocationId:831*location = SYSTEM_VALUE_INVOCATION_ID;832set_mode_system_value(b, mode);833break;834case SpvBuiltInLayer:835*location = VARYING_SLOT_LAYER;836if (b->shader->info.stage == MESA_SHADER_FRAGMENT)837*mode = nir_var_shader_in;838else if (b->shader->info.stage == MESA_SHADER_GEOMETRY)839*mode = nir_var_shader_out;840else if (b->options && b->options->caps.shader_viewport_index_layer &&841(b->shader->info.stage == MESA_SHADER_VERTEX ||842b->shader->info.stage == MESA_SHADER_TESS_EVAL))843*mode = nir_var_shader_out;844else845vtn_fail("invalid stage for SpvBuiltInLayer");846break;847case SpvBuiltInViewportIndex:848*location = VARYING_SLOT_VIEWPORT;849if (b->shader->info.stage == MESA_SHADER_GEOMETRY)850*mode = nir_var_shader_out;851else if (b->options && b->options->caps.shader_viewport_index_layer &&852(b->shader->info.stage == MESA_SHADER_VERTEX ||853b->shader->info.stage == MESA_SHADER_TESS_EVAL))854*mode = nir_var_shader_out;855else if (b->shader->info.stage == MESA_SHADER_FRAGMENT)856*mode = nir_var_shader_in;857else858vtn_fail("invalid stage for SpvBuiltInViewportIndex");859break;860case SpvBuiltInTessLevelOuter:861*location = VARYING_SLOT_TESS_LEVEL_OUTER;862break;863case SpvBuiltInTessLevelInner:864*location = VARYING_SLOT_TESS_LEVEL_INNER;865break;866case SpvBuiltInTessCoord:867*location = SYSTEM_VALUE_TESS_COORD;868set_mode_system_value(b, mode);869break;870case SpvBuiltInPatchVertices:871*location = SYSTEM_VALUE_VERTICES_IN;872set_mode_system_value(b, mode);873break;874case SpvBuiltInFragCoord:875vtn_assert(*mode == nir_var_shader_in);876if (b->options && b->options->frag_coord_is_sysval) {877*mode = nir_var_system_value;878*location = SYSTEM_VALUE_FRAG_COORD;879} else {880*location = VARYING_SLOT_POS;881}882break;883case SpvBuiltInPointCoord:884*location = VARYING_SLOT_PNTC;885vtn_assert(*mode == nir_var_shader_in);886break;887case SpvBuiltInFrontFacing:888*location = SYSTEM_VALUE_FRONT_FACE;889set_mode_system_value(b, mode);890break;891case SpvBuiltInSampleId:892*location = SYSTEM_VALUE_SAMPLE_ID;893set_mode_system_value(b, mode);894break;895case SpvBuiltInSamplePosition:896*location = SYSTEM_VALUE_SAMPLE_POS;897set_mode_system_value(b, mode);898break;899case SpvBuiltInSampleMask:900if (*mode == nir_var_shader_out) {901*location = FRAG_RESULT_SAMPLE_MASK;902} else {903*location = SYSTEM_VALUE_SAMPLE_MASK_IN;904set_mode_system_value(b, mode);905}906break;907case SpvBuiltInFragDepth:908*location = FRAG_RESULT_DEPTH;909vtn_assert(*mode == nir_var_shader_out);910break;911case SpvBuiltInHelperInvocation:912*location = SYSTEM_VALUE_HELPER_INVOCATION;913set_mode_system_value(b, mode);914break;915case SpvBuiltInNumWorkgroups:916*location = SYSTEM_VALUE_NUM_WORKGROUPS;917set_mode_system_value(b, mode);918break;919case SpvBuiltInWorkgroupSize:920case SpvBuiltInEnqueuedWorkgroupSize:921*location = SYSTEM_VALUE_WORKGROUP_SIZE;922set_mode_system_value(b, mode);923break;924case SpvBuiltInWorkgroupId:925*location = SYSTEM_VALUE_WORKGROUP_ID;926set_mode_system_value(b, mode);927break;928case SpvBuiltInLocalInvocationId:929*location = SYSTEM_VALUE_LOCAL_INVOCATION_ID;930set_mode_system_value(b, mode);931break;932case SpvBuiltInLocalInvocationIndex:933*location = SYSTEM_VALUE_LOCAL_INVOCATION_INDEX;934set_mode_system_value(b, mode);935break;936case SpvBuiltInGlobalInvocationId:937*location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID;938set_mode_system_value(b, mode);939break;940case SpvBuiltInGlobalLinearId:941*location = SYSTEM_VALUE_GLOBAL_INVOCATION_INDEX;942set_mode_system_value(b, mode);943break;944case SpvBuiltInGlobalOffset:945*location = SYSTEM_VALUE_BASE_GLOBAL_INVOCATION_ID;946set_mode_system_value(b, mode);947break;948case SpvBuiltInBaseVertex:949/* OpenGL gl_BaseVertex (SYSTEM_VALUE_BASE_VERTEX) is not the same950* semantic as Vulkan BaseVertex (SYSTEM_VALUE_FIRST_VERTEX).951*/952if (b->options->environment == NIR_SPIRV_OPENGL)953*location = SYSTEM_VALUE_BASE_VERTEX;954else955*location = SYSTEM_VALUE_FIRST_VERTEX;956set_mode_system_value(b, mode);957break;958case SpvBuiltInBaseInstance:959*location = SYSTEM_VALUE_BASE_INSTANCE;960set_mode_system_value(b, mode);961break;962case SpvBuiltInDrawIndex:963*location = SYSTEM_VALUE_DRAW_ID;964set_mode_system_value(b, mode);965break;966case SpvBuiltInSubgroupSize:967*location = SYSTEM_VALUE_SUBGROUP_SIZE;968set_mode_system_value(b, mode);969break;970case SpvBuiltInSubgroupId:971*location = SYSTEM_VALUE_SUBGROUP_ID;972set_mode_system_value(b, mode);973break;974case SpvBuiltInSubgroupLocalInvocationId:975*location = SYSTEM_VALUE_SUBGROUP_INVOCATION;976set_mode_system_value(b, mode);977break;978case SpvBuiltInNumSubgroups:979*location = SYSTEM_VALUE_NUM_SUBGROUPS;980set_mode_system_value(b, mode);981break;982case SpvBuiltInDeviceIndex:983*location = SYSTEM_VALUE_DEVICE_INDEX;984set_mode_system_value(b, mode);985break;986case SpvBuiltInViewIndex:987if (b->options && b->options->view_index_is_input) {988*location = VARYING_SLOT_VIEW_INDEX;989vtn_assert(*mode == nir_var_shader_in);990} else {991*location = SYSTEM_VALUE_VIEW_INDEX;992set_mode_system_value(b, mode);993}994break;995case SpvBuiltInSubgroupEqMask:996*location = SYSTEM_VALUE_SUBGROUP_EQ_MASK,997set_mode_system_value(b, mode);998break;999case SpvBuiltInSubgroupGeMask:1000*location = SYSTEM_VALUE_SUBGROUP_GE_MASK,1001set_mode_system_value(b, mode);1002break;1003case SpvBuiltInSubgroupGtMask:1004*location = SYSTEM_VALUE_SUBGROUP_GT_MASK,1005set_mode_system_value(b, mode);1006break;1007case SpvBuiltInSubgroupLeMask:1008*location = SYSTEM_VALUE_SUBGROUP_LE_MASK,1009set_mode_system_value(b, mode);1010break;1011case SpvBuiltInSubgroupLtMask:1012*location = SYSTEM_VALUE_SUBGROUP_LT_MASK,1013set_mode_system_value(b, mode);1014break;1015case SpvBuiltInFragStencilRefEXT:1016*location = FRAG_RESULT_STENCIL;1017vtn_assert(*mode == nir_var_shader_out);1018break;1019case SpvBuiltInWorkDim:1020*location = SYSTEM_VALUE_WORK_DIM;1021set_mode_system_value(b, mode);1022break;1023case SpvBuiltInGlobalSize:1024*location = SYSTEM_VALUE_GLOBAL_GROUP_SIZE;1025set_mode_system_value(b, mode);1026break;1027case SpvBuiltInBaryCoordNoPerspAMD:1028*location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_PIXEL;1029set_mode_system_value(b, mode);1030break;1031case SpvBuiltInBaryCoordNoPerspCentroidAMD:1032*location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID;1033set_mode_system_value(b, mode);1034break;1035case SpvBuiltInBaryCoordNoPerspSampleAMD:1036*location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE;1037set_mode_system_value(b, mode);1038break;1039case SpvBuiltInBaryCoordSmoothAMD:1040*location = SYSTEM_VALUE_BARYCENTRIC_PERSP_PIXEL;1041set_mode_system_value(b, mode);1042break;1043case SpvBuiltInBaryCoordSmoothCentroidAMD:1044*location = SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID;1045set_mode_system_value(b, mode);1046break;1047case SpvBuiltInBaryCoordSmoothSampleAMD:1048*location = SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE;1049set_mode_system_value(b, mode);1050break;1051case SpvBuiltInBaryCoordPullModelAMD:1052*location = SYSTEM_VALUE_BARYCENTRIC_PULL_MODEL;1053set_mode_system_value(b, mode);1054break;1055case SpvBuiltInLaunchIdKHR:1056*location = SYSTEM_VALUE_RAY_LAUNCH_ID;1057set_mode_system_value(b, mode);1058break;1059case SpvBuiltInLaunchSizeKHR:1060*location = SYSTEM_VALUE_RAY_LAUNCH_SIZE;1061set_mode_system_value(b, mode);1062break;1063case SpvBuiltInWorldRayOriginKHR:1064*location = SYSTEM_VALUE_RAY_WORLD_ORIGIN;1065set_mode_system_value(b, mode);1066break;1067case SpvBuiltInWorldRayDirectionKHR:1068*location = SYSTEM_VALUE_RAY_WORLD_DIRECTION;1069set_mode_system_value(b, mode);1070break;1071case SpvBuiltInObjectRayOriginKHR:1072*location = SYSTEM_VALUE_RAY_OBJECT_ORIGIN;1073set_mode_system_value(b, mode);1074break;1075case SpvBuiltInObjectRayDirectionKHR:1076*location = SYSTEM_VALUE_RAY_OBJECT_DIRECTION;1077set_mode_system_value(b, mode);1078break;1079case SpvBuiltInObjectToWorldKHR:1080*location = SYSTEM_VALUE_RAY_OBJECT_TO_WORLD;1081set_mode_system_value(b, mode);1082break;1083case SpvBuiltInWorldToObjectKHR:1084*location = SYSTEM_VALUE_RAY_WORLD_TO_OBJECT;1085set_mode_system_value(b, mode);1086break;1087case SpvBuiltInRayTminKHR:1088*location = SYSTEM_VALUE_RAY_T_MIN;1089set_mode_system_value(b, mode);1090break;1091case SpvBuiltInRayTmaxKHR:1092case SpvBuiltInHitTNV:1093*location = SYSTEM_VALUE_RAY_T_MAX;1094set_mode_system_value(b, mode);1095break;1096case SpvBuiltInInstanceCustomIndexKHR:1097*location = SYSTEM_VALUE_RAY_INSTANCE_CUSTOM_INDEX;1098set_mode_system_value(b, mode);1099break;1100case SpvBuiltInHitKindKHR:1101*location = SYSTEM_VALUE_RAY_HIT_KIND;1102set_mode_system_value(b, mode);1103break;1104case SpvBuiltInIncomingRayFlagsKHR:1105*location = SYSTEM_VALUE_RAY_FLAGS;1106set_mode_system_value(b, mode);1107break;1108case SpvBuiltInRayGeometryIndexKHR:1109*location = SYSTEM_VALUE_RAY_GEOMETRY_INDEX;1110set_mode_system_value(b, mode);1111break;1112case SpvBuiltInShadingRateKHR:1113*location = SYSTEM_VALUE_FRAG_SHADING_RATE;1114set_mode_system_value(b, mode);1115break;1116case SpvBuiltInPrimitiveShadingRateKHR:1117if (b->shader->info.stage == MESA_SHADER_VERTEX ||1118b->shader->info.stage == MESA_SHADER_GEOMETRY) {1119*location = VARYING_SLOT_PRIMITIVE_SHADING_RATE;1120*mode = nir_var_shader_out;1121} else {1122vtn_fail("invalid stage for SpvBuiltInPrimitiveShadingRateKHR");1123}1124break;1125default:1126vtn_fail("Unsupported builtin: %s (%u)",1127spirv_builtin_to_string(builtin), builtin);1128}1129}11301131static void1132apply_var_decoration(struct vtn_builder *b,1133struct nir_variable_data *var_data,1134const struct vtn_decoration *dec)1135{1136switch (dec->decoration) {1137case SpvDecorationRelaxedPrecision:1138break; /* FIXME: Do nothing with this for now. */1139case SpvDecorationNoPerspective:1140var_data->interpolation = INTERP_MODE_NOPERSPECTIVE;1141break;1142case SpvDecorationFlat:1143var_data->interpolation = INTERP_MODE_FLAT;1144break;1145case SpvDecorationExplicitInterpAMD:1146var_data->interpolation = INTERP_MODE_EXPLICIT;1147break;1148case SpvDecorationCentroid:1149var_data->centroid = true;1150break;1151case SpvDecorationSample:1152var_data->sample = true;1153break;1154case SpvDecorationInvariant:1155var_data->invariant = true;1156break;1157case SpvDecorationConstant:1158var_data->read_only = true;1159break;1160case SpvDecorationNonReadable:1161var_data->access |= ACCESS_NON_READABLE;1162break;1163case SpvDecorationNonWritable:1164var_data->read_only = true;1165var_data->access |= ACCESS_NON_WRITEABLE;1166break;1167case SpvDecorationRestrict:1168var_data->access |= ACCESS_RESTRICT;1169break;1170case SpvDecorationAliased:1171var_data->access &= ~ACCESS_RESTRICT;1172break;1173case SpvDecorationVolatile:1174var_data->access |= ACCESS_VOLATILE;1175break;1176case SpvDecorationCoherent:1177var_data->access |= ACCESS_COHERENT;1178break;1179case SpvDecorationComponent:1180var_data->location_frac = dec->operands[0];1181break;1182case SpvDecorationIndex:1183var_data->index = dec->operands[0];1184break;1185case SpvDecorationBuiltIn: {1186SpvBuiltIn builtin = dec->operands[0];11871188nir_variable_mode mode = var_data->mode;1189vtn_get_builtin_location(b, builtin, &var_data->location, &mode);1190var_data->mode = mode;11911192switch (builtin) {1193case SpvBuiltInTessLevelOuter:1194case SpvBuiltInTessLevelInner:1195case SpvBuiltInClipDistance:1196case SpvBuiltInCullDistance:1197var_data->compact = true;1198break;1199default:1200break;1201}12021203break;1204}12051206case SpvDecorationSpecId:1207case SpvDecorationRowMajor:1208case SpvDecorationColMajor:1209case SpvDecorationMatrixStride:1210case SpvDecorationUniform:1211case SpvDecorationUniformId:1212case SpvDecorationLinkageAttributes:1213break; /* Do nothing with these here */12141215case SpvDecorationPatch:1216var_data->patch = true;1217break;12181219case SpvDecorationLocation:1220vtn_fail("Should be handled earlier by var_decoration_cb()");12211222case SpvDecorationBlock:1223case SpvDecorationBufferBlock:1224case SpvDecorationArrayStride:1225case SpvDecorationGLSLShared:1226case SpvDecorationGLSLPacked:1227break; /* These can apply to a type but we don't care about them */12281229case SpvDecorationBinding:1230case SpvDecorationDescriptorSet:1231case SpvDecorationNoContraction:1232case SpvDecorationInputAttachmentIndex:1233vtn_warn("Decoration not allowed for variable or structure member: %s",1234spirv_decoration_to_string(dec->decoration));1235break;12361237case SpvDecorationXfbBuffer:1238var_data->explicit_xfb_buffer = true;1239var_data->xfb.buffer = dec->operands[0];1240var_data->always_active_io = true;1241break;1242case SpvDecorationXfbStride:1243var_data->explicit_xfb_stride = true;1244var_data->xfb.stride = dec->operands[0];1245break;1246case SpvDecorationOffset:1247var_data->explicit_offset = true;1248var_data->offset = dec->operands[0];1249break;12501251case SpvDecorationStream:1252var_data->stream = dec->operands[0];1253break;12541255case SpvDecorationCPacked:1256case SpvDecorationSaturatedConversion:1257case SpvDecorationFuncParamAttr:1258case SpvDecorationFPRoundingMode:1259case SpvDecorationFPFastMathMode:1260case SpvDecorationAlignment:1261if (b->shader->info.stage != MESA_SHADER_KERNEL) {1262vtn_warn("Decoration only allowed for CL-style kernels: %s",1263spirv_decoration_to_string(dec->decoration));1264}1265break;12661267case SpvDecorationUserSemantic:1268case SpvDecorationUserTypeGOOGLE:1269/* User semantic decorations can safely be ignored by the driver. */1270break;12711272case SpvDecorationRestrictPointerEXT:1273case SpvDecorationAliasedPointerEXT:1274/* TODO: We should actually plumb alias information through NIR. */1275break;12761277default:1278vtn_fail_with_decoration("Unhandled decoration", dec->decoration);1279}1280}12811282static void1283var_is_patch_cb(struct vtn_builder *b, struct vtn_value *val, int member,1284const struct vtn_decoration *dec, void *void_var)1285{1286struct vtn_variable *vtn_var = void_var;1287if (dec->decoration == SpvDecorationPatch)1288vtn_var->var->data.patch = true;1289}12901291static void1292var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,1293const struct vtn_decoration *dec, void *void_var)1294{1295struct vtn_variable *vtn_var = void_var;12961297/* Handle decorations that apply to a vtn_variable as a whole */1298switch (dec->decoration) {1299case SpvDecorationBinding:1300vtn_var->binding = dec->operands[0];1301vtn_var->explicit_binding = true;1302return;1303case SpvDecorationDescriptorSet:1304vtn_var->descriptor_set = dec->operands[0];1305return;1306case SpvDecorationInputAttachmentIndex:1307vtn_var->input_attachment_index = dec->operands[0];1308return;1309case SpvDecorationPatch:1310vtn_var->var->data.patch = true;1311break;1312case SpvDecorationOffset:1313vtn_var->offset = dec->operands[0];1314break;1315case SpvDecorationNonWritable:1316vtn_var->access |= ACCESS_NON_WRITEABLE;1317break;1318case SpvDecorationNonReadable:1319vtn_var->access |= ACCESS_NON_READABLE;1320break;1321case SpvDecorationVolatile:1322vtn_var->access |= ACCESS_VOLATILE;1323break;1324case SpvDecorationCoherent:1325vtn_var->access |= ACCESS_COHERENT;1326break;1327case SpvDecorationCounterBuffer:1328/* Counter buffer decorations can safely be ignored by the driver. */1329return;1330default:1331break;1332}13331334if (val->value_type == vtn_value_type_pointer) {1335assert(val->pointer->var == void_var);1336assert(member == -1);1337} else {1338assert(val->value_type == vtn_value_type_type);1339}13401341/* Location is odd. If applied to a split structure, we have to walk the1342* whole thing and accumulate the location. It's easier to handle as a1343* special case.1344*/1345if (dec->decoration == SpvDecorationLocation) {1346unsigned location = dec->operands[0];1347if (b->shader->info.stage == MESA_SHADER_FRAGMENT &&1348vtn_var->mode == vtn_variable_mode_output) {1349location += FRAG_RESULT_DATA0;1350} else if (b->shader->info.stage == MESA_SHADER_VERTEX &&1351vtn_var->mode == vtn_variable_mode_input) {1352location += VERT_ATTRIB_GENERIC0;1353} else if (vtn_var->mode == vtn_variable_mode_input ||1354vtn_var->mode == vtn_variable_mode_output) {1355location += vtn_var->var->data.patch ? VARYING_SLOT_PATCH0 : VARYING_SLOT_VAR0;1356} else if (vtn_var->mode == vtn_variable_mode_call_data ||1357vtn_var->mode == vtn_variable_mode_ray_payload) {1358/* This location is fine as-is */1359} else if (vtn_var->mode != vtn_variable_mode_uniform) {1360vtn_warn("Location must be on input, output, uniform, sampler or "1361"image variable");1362return;1363}13641365if (vtn_var->var->num_members == 0) {1366/* This handles the member and lone variable cases */1367vtn_var->var->data.location = location;1368} else {1369/* This handles the structure member case */1370assert(vtn_var->var->members);13711372if (member == -1)1373vtn_var->base_location = location;1374else1375vtn_var->var->members[member].location = location;1376}13771378return;1379} else {1380if (vtn_var->var) {1381if (vtn_var->var->num_members == 0) {1382/* We call this function on types as well as variables and not all1383* struct types get split so we can end up having stray member1384* decorations; just ignore them.1385*/1386if (member == -1)1387apply_var_decoration(b, &vtn_var->var->data, dec);1388} else if (member >= 0) {1389/* Member decorations must come from a type */1390assert(val->value_type == vtn_value_type_type);1391apply_var_decoration(b, &vtn_var->var->members[member], dec);1392} else {1393unsigned length =1394glsl_get_length(glsl_without_array(vtn_var->type->type));1395for (unsigned i = 0; i < length; i++)1396apply_var_decoration(b, &vtn_var->var->members[i], dec);1397}1398} else {1399/* A few variables, those with external storage, have no actual1400* nir_variables associated with them. Fortunately, all decorations1401* we care about for those variables are on the type only.1402*/1403vtn_assert(vtn_var->mode == vtn_variable_mode_ubo ||1404vtn_var->mode == vtn_variable_mode_ssbo ||1405vtn_var->mode == vtn_variable_mode_push_constant);1406}1407}1408}14091410enum vtn_variable_mode1411vtn_storage_class_to_mode(struct vtn_builder *b,1412SpvStorageClass class,1413struct vtn_type *interface_type,1414nir_variable_mode *nir_mode_out)1415{1416enum vtn_variable_mode mode;1417nir_variable_mode nir_mode;1418switch (class) {1419case SpvStorageClassUniform:1420/* Assume it's an UBO if we lack the interface_type. */1421if (!interface_type || interface_type->block) {1422mode = vtn_variable_mode_ubo;1423nir_mode = nir_var_mem_ubo;1424} else if (interface_type->buffer_block) {1425mode = vtn_variable_mode_ssbo;1426nir_mode = nir_var_mem_ssbo;1427} else {1428/* Default-block uniforms, coming from gl_spirv */1429mode = vtn_variable_mode_uniform;1430nir_mode = nir_var_uniform;1431}1432break;1433case SpvStorageClassStorageBuffer:1434mode = vtn_variable_mode_ssbo;1435nir_mode = nir_var_mem_ssbo;1436break;1437case SpvStorageClassPhysicalStorageBuffer:1438mode = vtn_variable_mode_phys_ssbo;1439nir_mode = nir_var_mem_global;1440break;1441case SpvStorageClassUniformConstant:1442if (b->shader->info.stage == MESA_SHADER_KERNEL) {1443mode = vtn_variable_mode_constant;1444nir_mode = nir_var_mem_constant;1445} else {1446/* interface_type is only NULL when OpTypeForwardPointer is used and1447* OpTypeForwardPointer cannot be used with the UniformConstant1448* storage class.1449*/1450assert(interface_type != NULL);1451interface_type = vtn_type_without_array(interface_type);1452if (interface_type->base_type == vtn_base_type_accel_struct) {1453mode = vtn_variable_mode_accel_struct;1454nir_mode = nir_var_uniform;1455} else {1456mode = vtn_variable_mode_uniform;1457nir_mode = nir_var_uniform;1458}1459}1460break;1461case SpvStorageClassPushConstant:1462mode = vtn_variable_mode_push_constant;1463nir_mode = nir_var_mem_push_const;1464break;1465case SpvStorageClassInput:1466mode = vtn_variable_mode_input;1467nir_mode = nir_var_shader_in;1468break;1469case SpvStorageClassOutput:1470mode = vtn_variable_mode_output;1471nir_mode = nir_var_shader_out;1472break;1473case SpvStorageClassPrivate:1474mode = vtn_variable_mode_private;1475nir_mode = nir_var_shader_temp;1476break;1477case SpvStorageClassFunction:1478mode = vtn_variable_mode_function;1479nir_mode = nir_var_function_temp;1480break;1481case SpvStorageClassWorkgroup:1482mode = vtn_variable_mode_workgroup;1483nir_mode = nir_var_mem_shared;1484break;1485case SpvStorageClassAtomicCounter:1486mode = vtn_variable_mode_atomic_counter;1487nir_mode = nir_var_uniform;1488break;1489case SpvStorageClassCrossWorkgroup:1490mode = vtn_variable_mode_cross_workgroup;1491nir_mode = nir_var_mem_global;1492break;1493case SpvStorageClassImage:1494mode = vtn_variable_mode_image;1495nir_mode = nir_var_mem_ubo;1496break;1497case SpvStorageClassCallableDataKHR:1498mode = vtn_variable_mode_call_data;1499nir_mode = nir_var_shader_temp;1500break;1501case SpvStorageClassIncomingCallableDataKHR:1502mode = vtn_variable_mode_call_data_in;1503nir_mode = nir_var_shader_call_data;1504break;1505case SpvStorageClassRayPayloadKHR:1506mode = vtn_variable_mode_ray_payload;1507nir_mode = nir_var_shader_temp;1508break;1509case SpvStorageClassIncomingRayPayloadKHR:1510mode = vtn_variable_mode_ray_payload_in;1511nir_mode = nir_var_shader_call_data;1512break;1513case SpvStorageClassHitAttributeKHR:1514mode = vtn_variable_mode_hit_attrib;1515nir_mode = nir_var_ray_hit_attrib;1516break;1517case SpvStorageClassShaderRecordBufferKHR:1518mode = vtn_variable_mode_shader_record;1519nir_mode = nir_var_mem_constant;1520break;15211522case SpvStorageClassGeneric:1523mode = vtn_variable_mode_generic;1524nir_mode = nir_var_mem_generic;1525break;1526default:1527vtn_fail("Unhandled variable storage class: %s (%u)",1528spirv_storageclass_to_string(class), class);1529}15301531if (nir_mode_out)1532*nir_mode_out = nir_mode;15331534return mode;1535}15361537nir_address_format1538vtn_mode_to_address_format(struct vtn_builder *b, enum vtn_variable_mode mode)1539{1540switch (mode) {1541case vtn_variable_mode_ubo:1542return b->options->ubo_addr_format;15431544case vtn_variable_mode_ssbo:1545return b->options->ssbo_addr_format;15461547case vtn_variable_mode_phys_ssbo:1548return b->options->phys_ssbo_addr_format;15491550case vtn_variable_mode_push_constant:1551return b->options->push_const_addr_format;15521553case vtn_variable_mode_workgroup:1554return b->options->shared_addr_format;15551556case vtn_variable_mode_generic:1557case vtn_variable_mode_cross_workgroup:1558return b->options->global_addr_format;15591560case vtn_variable_mode_shader_record:1561case vtn_variable_mode_constant:1562return b->options->constant_addr_format;15631564case vtn_variable_mode_accel_struct:1565return nir_address_format_64bit_global;15661567case vtn_variable_mode_function:1568if (b->physical_ptrs)1569return b->options->temp_addr_format;1570FALLTHROUGH;15711572case vtn_variable_mode_private:1573case vtn_variable_mode_uniform:1574case vtn_variable_mode_atomic_counter:1575case vtn_variable_mode_input:1576case vtn_variable_mode_output:1577case vtn_variable_mode_image:1578case vtn_variable_mode_call_data:1579case vtn_variable_mode_call_data_in:1580case vtn_variable_mode_ray_payload:1581case vtn_variable_mode_ray_payload_in:1582case vtn_variable_mode_hit_attrib:1583return nir_address_format_logical;1584}15851586unreachable("Invalid variable mode");1587}15881589nir_ssa_def *1590vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr)1591{1592if ((vtn_pointer_is_external_block(b, ptr) &&1593vtn_type_contains_block(b, ptr->type) &&1594ptr->mode != vtn_variable_mode_phys_ssbo) ||1595ptr->mode == vtn_variable_mode_accel_struct) {1596/* In this case, we're looking for a block index and not an actual1597* deref.1598*1599* For PhysicalStorageBuffer pointers, we don't have a block index1600* at all because we get the pointer directly from the client. This1601* assumes that there will never be a SSBO binding variable using the1602* PhysicalStorageBuffer storage class. This assumption appears1603* to be correct according to the Vulkan spec because the table,1604* "Shader Resource and Storage Class Correspondence," the only the1605* Uniform storage class with BufferBlock or the StorageBuffer1606* storage class with Block can be used.1607*/1608if (!ptr->block_index) {1609/* If we don't have a block_index then we must be a pointer to the1610* variable itself.1611*/1612vtn_assert(!ptr->deref);16131614struct vtn_access_chain chain = {1615.length = 0,1616};1617ptr = vtn_pointer_dereference(b, ptr, &chain);1618}16191620return ptr->block_index;1621} else {1622return &vtn_pointer_to_deref(b, ptr)->dest.ssa;1623}1624}16251626struct vtn_pointer *1627vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,1628struct vtn_type *ptr_type)1629{1630vtn_assert(ptr_type->base_type == vtn_base_type_pointer);16311632struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);1633struct vtn_type *without_array =1634vtn_type_without_array(ptr_type->deref);16351636nir_variable_mode nir_mode;1637ptr->mode = vtn_storage_class_to_mode(b, ptr_type->storage_class,1638without_array, &nir_mode);1639ptr->type = ptr_type->deref;1640ptr->ptr_type = ptr_type;16411642const struct glsl_type *deref_type =1643vtn_type_get_nir_type(b, ptr_type->deref, ptr->mode);1644if (!vtn_pointer_is_external_block(b, ptr) &&1645ptr->mode != vtn_variable_mode_accel_struct) {1646ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,1647deref_type, ptr_type->stride);1648} else if ((vtn_type_contains_block(b, ptr->type) &&1649ptr->mode != vtn_variable_mode_phys_ssbo) ||1650ptr->mode == vtn_variable_mode_accel_struct) {1651/* This is a pointer to somewhere in an array of blocks, not a1652* pointer to somewhere inside the block. Set the block index1653* instead of making a cast.1654*/1655ptr->block_index = ssa;1656} else {1657/* This is a pointer to something internal or a pointer inside a1658* block. It's just a regular cast.1659*1660* For PhysicalStorageBuffer pointers, we don't have a block index1661* at all because we get the pointer directly from the client. This1662* assumes that there will never be a SSBO binding variable using the1663* PhysicalStorageBuffer storage class. This assumption appears1664* to be correct according to the Vulkan spec because the table,1665* "Shader Resource and Storage Class Correspondence," the only the1666* Uniform storage class with BufferBlock or the StorageBuffer1667* storage class with Block can be used.1668*/1669ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,1670deref_type, ptr_type->stride);1671ptr->deref->dest.ssa.num_components =1672glsl_get_vector_elements(ptr_type->type);1673ptr->deref->dest.ssa.bit_size = glsl_get_bit_size(ptr_type->type);1674}16751676return ptr;1677}16781679static void1680assign_missing_member_locations(struct vtn_variable *var)1681{1682unsigned length =1683glsl_get_length(glsl_without_array(var->type->type));1684int location = var->base_location;16851686for (unsigned i = 0; i < length; i++) {1687/* From the Vulkan spec:1688*1689* “If the structure type is a Block but without a Location, then each1690* of its members must have a Location decoration.”1691*1692*/1693if (var->type->block) {1694assert(var->base_location != -1 ||1695var->var->members[i].location != -1);1696}16971698/* From the Vulkan spec:1699*1700* “Any member with its own Location decoration is assigned that1701* location. Each remaining member is assigned the location after the1702* immediately preceding member in declaration order.”1703*/1704if (var->var->members[i].location != -1)1705location = var->var->members[i].location;1706else1707var->var->members[i].location = location;17081709/* Below we use type instead of interface_type, because interface_type1710* is only available when it is a Block. This code also supports1711* input/outputs that are just structs1712*/1713const struct glsl_type *member_type =1714glsl_get_struct_field(glsl_without_array(var->type->type), i);17151716location +=1717glsl_count_attribute_slots(member_type,1718false /* is_gl_vertex_input */);1719}1720}17211722nir_deref_instr *1723vtn_get_call_payload_for_location(struct vtn_builder *b, uint32_t location_id)1724{1725uint32_t location = vtn_constant_uint(b, location_id);1726nir_foreach_variable_with_modes(var, b->nb.shader, nir_var_shader_temp) {1727if (var->data.explicit_location &&1728var->data.location == location)1729return nir_build_deref_var(&b->nb, var);1730}1731vtn_fail("Couldn't find variable with a storage class of CallableDataKHR "1732"or RayPayloadKHR and location %d", location);1733}17341735static void1736vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,1737struct vtn_type *ptr_type, SpvStorageClass storage_class,1738struct vtn_value *initializer)1739{1740vtn_assert(ptr_type->base_type == vtn_base_type_pointer);1741struct vtn_type *type = ptr_type->deref;17421743struct vtn_type *without_array = vtn_type_without_array(ptr_type->deref);17441745enum vtn_variable_mode mode;1746nir_variable_mode nir_mode;1747mode = vtn_storage_class_to_mode(b, storage_class, without_array, &nir_mode);17481749switch (mode) {1750case vtn_variable_mode_ubo:1751/* There's no other way to get vtn_variable_mode_ubo */1752vtn_assert(without_array->block);1753break;1754case vtn_variable_mode_ssbo:1755if (storage_class == SpvStorageClassStorageBuffer &&1756!without_array->block) {1757if (b->variable_pointers) {1758vtn_fail("Variables in the StorageBuffer storage class must "1759"have a struct type with the Block decoration");1760} else {1761/* If variable pointers are not present, it's still malformed1762* SPIR-V but we can parse it and do the right thing anyway.1763* Since some of the 8-bit storage tests have bugs in this are,1764* just make it a warning for now.1765*/1766vtn_warn("Variables in the StorageBuffer storage class must "1767"have a struct type with the Block decoration");1768}1769}1770break;17711772case vtn_variable_mode_generic:1773vtn_fail("Cannot create a variable with the Generic storage class");1774break;17751776case vtn_variable_mode_image:1777vtn_fail("Cannot create a variable with the Image storage class");1778break;17791780case vtn_variable_mode_phys_ssbo:1781vtn_fail("Cannot create a variable with the "1782"PhysicalStorageBuffer storage class");1783break;17841785default:1786/* No tallying is needed */1787break;1788}17891790struct vtn_variable *var = rzalloc(b, struct vtn_variable);1791var->type = type;1792var->mode = mode;1793var->base_location = -1;17941795val->pointer = rzalloc(b, struct vtn_pointer);1796val->pointer->mode = var->mode;1797val->pointer->type = var->type;1798val->pointer->ptr_type = ptr_type;1799val->pointer->var = var;1800val->pointer->access = var->type->access;18011802switch (var->mode) {1803case vtn_variable_mode_function:1804case vtn_variable_mode_private:1805case vtn_variable_mode_uniform:1806case vtn_variable_mode_atomic_counter:1807case vtn_variable_mode_constant:1808case vtn_variable_mode_call_data:1809case vtn_variable_mode_call_data_in:1810case vtn_variable_mode_ray_payload:1811case vtn_variable_mode_ray_payload_in:1812case vtn_variable_mode_hit_attrib:1813/* For these, we create the variable normally */1814var->var = rzalloc(b->shader, nir_variable);1815var->var->name = ralloc_strdup(var->var, val->name);1816var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);18171818/* This is a total hack but we need some way to flag variables which are1819* going to be call payloads. See get_call_payload_deref.1820*/1821if (storage_class == SpvStorageClassCallableDataKHR ||1822storage_class == SpvStorageClassRayPayloadKHR)1823var->var->data.explicit_location = true;18241825var->var->data.mode = nir_mode;1826var->var->data.location = -1;1827var->var->interface_type = NULL;1828break;18291830case vtn_variable_mode_ubo:1831case vtn_variable_mode_ssbo:1832case vtn_variable_mode_push_constant:1833case vtn_variable_mode_accel_struct:1834case vtn_variable_mode_shader_record:1835var->var = rzalloc(b->shader, nir_variable);1836var->var->name = ralloc_strdup(var->var, val->name);18371838var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);1839var->var->interface_type = var->var->type;18401841var->var->data.mode = nir_mode;1842var->var->data.location = -1;1843var->var->data.driver_location = 0;1844var->var->data.access = var->type->access;1845break;18461847case vtn_variable_mode_workgroup:1848case vtn_variable_mode_cross_workgroup:1849/* Create the variable normally */1850var->var = rzalloc(b->shader, nir_variable);1851var->var->name = ralloc_strdup(var->var, val->name);1852var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);1853var->var->data.mode = nir_mode;1854break;18551856case vtn_variable_mode_input:1857case vtn_variable_mode_output: {1858var->var = rzalloc(b->shader, nir_variable);1859var->var->name = ralloc_strdup(var->var, val->name);1860var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);1861var->var->data.mode = nir_mode;18621863/* In order to know whether or not we're a per-vertex inout, we need1864* the patch qualifier. This means walking the variable decorations1865* early before we actually create any variables. Not a big deal.1866*1867* GLSLang really likes to place decorations in the most interior1868* thing it possibly can. In particular, if you have a struct, it1869* will place the patch decorations on the struct members. This1870* should be handled by the variable splitting below just fine.1871*1872* If you have an array-of-struct, things get even more weird as it1873* will place the patch decorations on the struct even though it's1874* inside an array and some of the members being patch and others not1875* makes no sense whatsoever. Since the only sensible thing is for1876* it to be all or nothing, we'll call it patch if any of the members1877* are declared patch.1878*/1879vtn_foreach_decoration(b, val, var_is_patch_cb, var);1880if (glsl_type_is_array(var->type->type) &&1881glsl_type_is_struct_or_ifc(without_array->type)) {1882vtn_foreach_decoration(b, vtn_value(b, without_array->id,1883vtn_value_type_type),1884var_is_patch_cb, var);1885}18861887struct vtn_type *per_vertex_type = var->type;1888if (nir_is_arrayed_io(var->var, b->shader->info.stage))1889per_vertex_type = var->type->array_element;18901891/* Figure out the interface block type. */1892struct vtn_type *iface_type = per_vertex_type;1893if (var->mode == vtn_variable_mode_output &&1894(b->shader->info.stage == MESA_SHADER_VERTEX ||1895b->shader->info.stage == MESA_SHADER_TESS_EVAL ||1896b->shader->info.stage == MESA_SHADER_GEOMETRY)) {1897/* For vertex data outputs, we can end up with arrays of blocks for1898* transform feedback where each array element corresponds to a1899* different XFB output buffer.1900*/1901while (iface_type->base_type == vtn_base_type_array)1902iface_type = iface_type->array_element;1903}1904if (iface_type->base_type == vtn_base_type_struct && iface_type->block)1905var->var->interface_type = vtn_type_get_nir_type(b, iface_type,1906var->mode);19071908/* If it's a block, set it up as per-member so can be splitted later by1909* nir_split_per_member_structs.1910*1911* This is for a couple of reasons. For one, builtins may all come in a1912* block and we really want those split out into separate variables.1913* For another, interpolation qualifiers can be applied to members of1914* the top-level struct and we need to be able to preserve that1915* information.1916*/1917if (per_vertex_type->base_type == vtn_base_type_struct &&1918per_vertex_type->block) {1919var->var->num_members = glsl_get_length(per_vertex_type->type);1920var->var->members = rzalloc_array(var->var, struct nir_variable_data,1921var->var->num_members);19221923for (unsigned i = 0; i < var->var->num_members; i++) {1924var->var->members[i].mode = nir_mode;1925var->var->members[i].patch = var->var->data.patch;1926var->var->members[i].location = -1;1927}1928}19291930/* For inputs and outputs, we need to grab locations and builtin1931* information from the per-vertex type.1932*/1933vtn_foreach_decoration(b, vtn_value(b, per_vertex_type->id,1934vtn_value_type_type),1935var_decoration_cb, var);1936break;1937}19381939case vtn_variable_mode_image:1940case vtn_variable_mode_phys_ssbo:1941case vtn_variable_mode_generic:1942unreachable("Should have been caught before");1943}19441945if (initializer) {1946switch (storage_class) {1947case SpvStorageClassWorkgroup:1948/* VK_KHR_zero_initialize_workgroup_memory. */1949vtn_fail_if(b->options->environment != NIR_SPIRV_VULKAN,1950"Only Vulkan supports variable initializer "1951"for Workgroup variable %u",1952vtn_id_for_value(b, val));1953vtn_fail_if(initializer->value_type != vtn_value_type_constant ||1954!initializer->is_null_constant,1955"Workgroup variable %u can only have OpConstantNull "1956"as initializer, but have %u instead",1957vtn_id_for_value(b, val),1958vtn_id_for_value(b, initializer));1959b->shader->info.zero_initialize_shared_memory = true;1960break;19611962case SpvStorageClassUniformConstant:1963vtn_fail_if(b->options->environment != NIR_SPIRV_OPENGL &&1964b->options->environment != NIR_SPIRV_OPENCL,1965"Only OpenGL and OpenCL support variable initializer "1966"for UniformConstant variable %u\n",1967vtn_id_for_value(b, val));1968vtn_fail_if(initializer->value_type != vtn_value_type_constant,1969"UniformConstant variable %u can only have a constant "1970"initializer, but have %u instead",1971vtn_id_for_value(b, val),1972vtn_id_for_value(b, initializer));1973break;19741975case SpvStorageClassOutput:1976case SpvStorageClassPrivate:1977vtn_assert(b->options->environment != NIR_SPIRV_OPENCL);1978/* These can have any initializer. */1979break;19801981case SpvStorageClassFunction:1982/* These can have any initializer. */1983break;19841985case SpvStorageClassCrossWorkgroup:1986vtn_assert(b->options->environment == NIR_SPIRV_OPENCL);1987vtn_fail("Initializer for CrossWorkgroup variable %u "1988"not yet supported in Mesa.",1989vtn_id_for_value(b, val));1990break;19911992default: {1993const enum nir_spirv_execution_environment env =1994b->options->environment;1995const char *env_name =1996env == NIR_SPIRV_VULKAN ? "Vulkan" :1997env == NIR_SPIRV_OPENCL ? "OpenCL" :1998env == NIR_SPIRV_OPENGL ? "OpenGL" :1999NULL;2000vtn_assert(env_name);2001vtn_fail("In %s, any OpVariable with an Initializer operand "2002"must have %s%s%s, or Function as "2003"its Storage Class operand. Variable %u has an "2004"Initializer but its Storage Class is %s.",2005env_name,2006env == NIR_SPIRV_VULKAN ? "Private, Output, Workgroup" : "",2007env == NIR_SPIRV_OPENCL ? "CrossWorkgroup, UniformConstant" : "",2008env == NIR_SPIRV_OPENGL ? "Private, Output, UniformConstant" : "",2009vtn_id_for_value(b, val),2010spirv_storageclass_to_string(storage_class));2011}2012}20132014switch (initializer->value_type) {2015case vtn_value_type_constant:2016var->var->constant_initializer =2017nir_constant_clone(initializer->constant, var->var);2018break;2019case vtn_value_type_pointer:2020var->var->pointer_initializer = initializer->pointer->var->var;2021break;2022default:2023vtn_fail("SPIR-V variable initializer %u must be constant or pointer",2024vtn_id_for_value(b, initializer));2025}2026}20272028if (var->mode == vtn_variable_mode_uniform ||2029var->mode == vtn_variable_mode_ssbo) {2030/* SSBOs and images are assumed to not alias in the Simple, GLSL and Vulkan memory models */2031var->var->data.access |= b->mem_model != SpvMemoryModelOpenCL ? ACCESS_RESTRICT : 0;2032}20332034vtn_foreach_decoration(b, val, var_decoration_cb, var);2035vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);20362037/* Propagate access flags from the OpVariable decorations. */2038val->pointer->access |= var->access;20392040if ((var->mode == vtn_variable_mode_input ||2041var->mode == vtn_variable_mode_output) &&2042var->var->members) {2043assign_missing_member_locations(var);2044}20452046if (var->mode == vtn_variable_mode_uniform ||2047var->mode == vtn_variable_mode_ubo ||2048var->mode == vtn_variable_mode_ssbo ||2049var->mode == vtn_variable_mode_atomic_counter) {2050/* XXX: We still need the binding information in the nir_variable2051* for these. We should fix that.2052*/2053var->var->data.binding = var->binding;2054var->var->data.explicit_binding = var->explicit_binding;2055var->var->data.descriptor_set = var->descriptor_set;2056var->var->data.index = var->input_attachment_index;2057var->var->data.offset = var->offset;20582059if (glsl_type_is_image(glsl_without_array(var->var->type)))2060var->var->data.image.format = without_array->image_format;2061}20622063if (var->mode == vtn_variable_mode_function) {2064vtn_assert(var->var != NULL && var->var->members == NULL);2065nir_function_impl_add_variable(b->nb.impl, var->var);2066} else if (var->var) {2067nir_shader_add_variable(b->shader, var->var);2068} else {2069vtn_assert(vtn_pointer_is_external_block(b, val->pointer) ||2070var->mode == vtn_variable_mode_accel_struct ||2071var->mode == vtn_variable_mode_shader_record);2072}2073}20742075static void2076vtn_assert_types_equal(struct vtn_builder *b, SpvOp opcode,2077struct vtn_type *dst_type,2078struct vtn_type *src_type)2079{2080if (dst_type->id == src_type->id)2081return;20822083if (vtn_types_compatible(b, dst_type, src_type)) {2084/* Early versions of GLSLang would re-emit types unnecessarily and you2085* would end up with OpLoad, OpStore, or OpCopyMemory opcodes which have2086* mismatched source and destination types.2087*2088* https://github.com/KhronosGroup/glslang/issues/3042089* https://github.com/KhronosGroup/glslang/issues/3072090* https://bugs.freedesktop.org/show_bug.cgi?id=1043382091* https://bugs.freedesktop.org/show_bug.cgi?id=1044242092*/2093vtn_warn("Source and destination types of %s do not have the same "2094"ID (but are compatible): %u vs %u",2095spirv_op_to_string(opcode), dst_type->id, src_type->id);2096return;2097}20982099vtn_fail("Source and destination types of %s do not match: %s vs. %s",2100spirv_op_to_string(opcode),2101glsl_get_type_name(dst_type->type),2102glsl_get_type_name(src_type->type));2103}21042105static nir_ssa_def *2106nir_shrink_zero_pad_vec(nir_builder *b, nir_ssa_def *val,2107unsigned num_components)2108{2109if (val->num_components == num_components)2110return val;21112112nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS];2113for (unsigned i = 0; i < num_components; i++) {2114if (i < val->num_components)2115comps[i] = nir_channel(b, val, i);2116else2117comps[i] = nir_imm_intN_t(b, 0, val->bit_size);2118}2119return nir_vec(b, comps, num_components);2120}21212122static nir_ssa_def *2123nir_sloppy_bitcast(nir_builder *b, nir_ssa_def *val,2124const struct glsl_type *type)2125{2126const unsigned num_components = glsl_get_vector_elements(type);2127const unsigned bit_size = glsl_get_bit_size(type);21282129/* First, zero-pad to ensure that the value is big enough that when we2130* bit-cast it, we don't loose anything.2131*/2132if (val->bit_size < bit_size) {2133const unsigned src_num_components_needed =2134vtn_align_u32(val->num_components, bit_size / val->bit_size);2135val = nir_shrink_zero_pad_vec(b, val, src_num_components_needed);2136}21372138val = nir_bitcast_vector(b, val, bit_size);21392140return nir_shrink_zero_pad_vec(b, val, num_components);2141}21422143static bool2144vtn_get_mem_operands(struct vtn_builder *b, const uint32_t *w, unsigned count,2145unsigned *idx, SpvMemoryAccessMask *access, unsigned *alignment,2146SpvScope *dest_scope, SpvScope *src_scope)2147{2148*access = 0;2149*alignment = 0;2150if (*idx >= count)2151return false;21522153*access = w[(*idx)++];2154if (*access & SpvMemoryAccessAlignedMask) {2155vtn_assert(*idx < count);2156*alignment = w[(*idx)++];2157}21582159if (*access & SpvMemoryAccessMakePointerAvailableMask) {2160vtn_assert(*idx < count);2161vtn_assert(dest_scope);2162*dest_scope = vtn_constant_uint(b, w[(*idx)++]);2163}21642165if (*access & SpvMemoryAccessMakePointerVisibleMask) {2166vtn_assert(*idx < count);2167vtn_assert(src_scope);2168*src_scope = vtn_constant_uint(b, w[(*idx)++]);2169}21702171return true;2172}21732174static enum gl_access_qualifier2175spv_access_to_gl_access(SpvMemoryAccessMask access)2176{2177if (access & SpvMemoryAccessVolatileMask)2178return ACCESS_VOLATILE;21792180return 0;2181}218221832184SpvMemorySemanticsMask2185vtn_mode_to_memory_semantics(enum vtn_variable_mode mode)2186{2187switch (mode) {2188case vtn_variable_mode_ssbo:2189case vtn_variable_mode_phys_ssbo:2190return SpvMemorySemanticsUniformMemoryMask;2191case vtn_variable_mode_workgroup:2192return SpvMemorySemanticsWorkgroupMemoryMask;2193case vtn_variable_mode_cross_workgroup:2194return SpvMemorySemanticsCrossWorkgroupMemoryMask;2195case vtn_variable_mode_atomic_counter:2196return SpvMemorySemanticsAtomicCounterMemoryMask;2197case vtn_variable_mode_image:2198return SpvMemorySemanticsImageMemoryMask;2199case vtn_variable_mode_output:2200return SpvMemorySemanticsOutputMemoryMask;2201default:2202return SpvMemorySemanticsMaskNone;2203}2204}22052206static void2207vtn_emit_make_visible_barrier(struct vtn_builder *b, SpvMemoryAccessMask access,2208SpvScope scope, enum vtn_variable_mode mode)2209{2210if (!(access & SpvMemoryAccessMakePointerVisibleMask))2211return;22122213vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeVisibleMask |2214SpvMemorySemanticsAcquireMask |2215vtn_mode_to_memory_semantics(mode));2216}22172218static void2219vtn_emit_make_available_barrier(struct vtn_builder *b, SpvMemoryAccessMask access,2220SpvScope scope, enum vtn_variable_mode mode)2221{2222if (!(access & SpvMemoryAccessMakePointerAvailableMask))2223return;22242225vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeAvailableMask |2226SpvMemorySemanticsReleaseMask |2227vtn_mode_to_memory_semantics(mode));2228}22292230static void2231ptr_nonuniform_workaround_cb(struct vtn_builder *b, struct vtn_value *val,2232int member, const struct vtn_decoration *dec, void *void_ptr)2233{2234enum gl_access_qualifier *access = void_ptr;22352236switch (dec->decoration) {2237case SpvDecorationNonUniformEXT:2238*access |= ACCESS_NON_UNIFORM;2239break;22402241default:2242break;2243}2244}22452246void2247vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,2248const uint32_t *w, unsigned count)2249{2250switch (opcode) {2251case SpvOpUndef: {2252struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);2253val->type = vtn_get_type(b, w[1]);2254break;2255}22562257case SpvOpVariable: {2258struct vtn_type *ptr_type = vtn_get_type(b, w[1]);22592260SpvStorageClass storage_class = w[3];22612262const bool is_global = storage_class != SpvStorageClassFunction;2263const bool is_io = storage_class == SpvStorageClassInput ||2264storage_class == SpvStorageClassOutput;22652266/* Skip global variables that are not used by the entrypoint. Before2267* SPIR-V 1.4 the interface is only used for I/O variables, so extra2268* variables will still need to be removed later.2269*/2270if (!b->options->create_library &&2271(is_io || (b->version >= 0x10400 && is_global))) {2272if (!bsearch(&w[2], b->interface_ids, b->interface_ids_count, 4, cmp_uint32_t))2273break;2274}22752276struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);2277struct vtn_value *initializer = count > 4 ? vtn_untyped_value(b, w[4]) : NULL;22782279vtn_create_variable(b, val, ptr_type, storage_class, initializer);22802281break;2282}22832284case SpvOpConstantSampler: {2285/* Synthesize a pointer-to-sampler type, create a variable of that type,2286* and give the variable a constant initializer with the sampler params */2287struct vtn_type *sampler_type = vtn_value(b, w[1], vtn_value_type_type)->type;2288struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);22892290struct vtn_type *ptr_type = rzalloc(b, struct vtn_type);2291ptr_type = rzalloc(b, struct vtn_type);2292ptr_type->base_type = vtn_base_type_pointer;2293ptr_type->deref = sampler_type;2294ptr_type->storage_class = SpvStorageClassUniform;22952296ptr_type->type = nir_address_format_to_glsl_type(2297vtn_mode_to_address_format(b, vtn_variable_mode_function));22982299vtn_create_variable(b, val, ptr_type, ptr_type->storage_class, NULL);23002301nir_variable *nir_var = val->pointer->var->var;2302nir_var->data.sampler.is_inline_sampler = true;2303nir_var->data.sampler.addressing_mode = w[3];2304nir_var->data.sampler.normalized_coordinates = w[4];2305nir_var->data.sampler.filter_mode = w[5];23062307break;2308}23092310case SpvOpAccessChain:2311case SpvOpPtrAccessChain:2312case SpvOpInBoundsAccessChain:2313case SpvOpInBoundsPtrAccessChain: {2314struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);2315enum gl_access_qualifier access = 0;2316chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain);23172318unsigned idx = 0;2319for (int i = 4; i < count; i++) {2320struct vtn_value *link_val = vtn_untyped_value(b, w[i]);2321if (link_val->value_type == vtn_value_type_constant) {2322chain->link[idx].mode = vtn_access_mode_literal;2323chain->link[idx].id = vtn_constant_int(b, w[i]);2324} else {2325chain->link[idx].mode = vtn_access_mode_id;2326chain->link[idx].id = w[i];2327}23282329/* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */2330vtn_foreach_decoration(b, link_val, ptr_nonuniform_workaround_cb, &access);23312332idx++;2333}23342335struct vtn_type *ptr_type = vtn_get_type(b, w[1]);2336struct vtn_pointer *base =2337vtn_value(b, w[3], vtn_value_type_pointer)->pointer;23382339/* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */2340access |= base->access & ACCESS_NON_UNIFORM;23412342struct vtn_pointer *ptr = vtn_pointer_dereference(b, base, chain);2343ptr->ptr_type = ptr_type;2344ptr->access |= access;2345vtn_push_pointer(b, w[2], ptr);2346break;2347}23482349case SpvOpCopyMemory: {2350struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer);2351struct vtn_value *src_val = vtn_value(b, w[2], vtn_value_type_pointer);2352struct vtn_pointer *dest = dest_val->pointer;2353struct vtn_pointer *src = src_val->pointer;23542355vtn_assert_types_equal(b, opcode, dest_val->type->deref,2356src_val->type->deref);23572358unsigned idx = 3, dest_alignment, src_alignment;2359SpvMemoryAccessMask dest_access, src_access;2360SpvScope dest_scope, src_scope;2361vtn_get_mem_operands(b, w, count, &idx, &dest_access, &dest_alignment,2362&dest_scope, &src_scope);2363if (!vtn_get_mem_operands(b, w, count, &idx, &src_access, &src_alignment,2364NULL, &src_scope)) {2365src_alignment = dest_alignment;2366src_access = dest_access;2367}2368src = vtn_align_pointer(b, src, src_alignment);2369dest = vtn_align_pointer(b, dest, dest_alignment);23702371vtn_emit_make_visible_barrier(b, src_access, src_scope, src->mode);23722373vtn_variable_copy(b, dest, src,2374spv_access_to_gl_access(dest_access),2375spv_access_to_gl_access(src_access));23762377vtn_emit_make_available_barrier(b, dest_access, dest_scope, dest->mode);2378break;2379}23802381case SpvOpCopyMemorySized: {2382struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer);2383struct vtn_value *src_val = vtn_value(b, w[2], vtn_value_type_pointer);2384nir_ssa_def *size = vtn_get_nir_ssa(b, w[3]);2385struct vtn_pointer *dest = dest_val->pointer;2386struct vtn_pointer *src = src_val->pointer;23872388unsigned idx = 4, dest_alignment, src_alignment;2389SpvMemoryAccessMask dest_access, src_access;2390SpvScope dest_scope, src_scope;2391vtn_get_mem_operands(b, w, count, &idx, &dest_access, &dest_alignment,2392&dest_scope, &src_scope);2393if (!vtn_get_mem_operands(b, w, count, &idx, &src_access, &src_alignment,2394NULL, &src_scope)) {2395src_alignment = dest_alignment;2396src_access = dest_access;2397}2398src = vtn_align_pointer(b, src, src_alignment);2399dest = vtn_align_pointer(b, dest, dest_alignment);24002401vtn_emit_make_visible_barrier(b, src_access, src_scope, src->mode);24022403nir_memcpy_deref_with_access(&b->nb,2404vtn_pointer_to_deref(b, dest),2405vtn_pointer_to_deref(b, src),2406size,2407spv_access_to_gl_access(dest_access),2408spv_access_to_gl_access(src_access));24092410vtn_emit_make_available_barrier(b, dest_access, dest_scope, dest->mode);2411break;2412}24132414case SpvOpLoad: {2415struct vtn_type *res_type = vtn_get_type(b, w[1]);2416struct vtn_value *src_val = vtn_value(b, w[3], vtn_value_type_pointer);2417struct vtn_pointer *src = src_val->pointer;24182419vtn_assert_types_equal(b, opcode, res_type, src_val->type->deref);24202421unsigned idx = 4, alignment;2422SpvMemoryAccessMask access;2423SpvScope scope;2424vtn_get_mem_operands(b, w, count, &idx, &access, &alignment, NULL, &scope);2425src = vtn_align_pointer(b, src, alignment);24262427vtn_emit_make_visible_barrier(b, access, scope, src->mode);24282429vtn_push_ssa_value(b, w[2], vtn_variable_load(b, src, spv_access_to_gl_access(access)));2430break;2431}24322433case SpvOpStore: {2434struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer);2435struct vtn_pointer *dest = dest_val->pointer;2436struct vtn_value *src_val = vtn_untyped_value(b, w[2]);24372438/* OpStore requires us to actually have a storage type */2439vtn_fail_if(dest->type->type == NULL,2440"Invalid destination type for OpStore");24412442if (glsl_get_base_type(dest->type->type) == GLSL_TYPE_BOOL &&2443glsl_get_base_type(src_val->type->type) == GLSL_TYPE_UINT) {2444/* Early versions of GLSLang would use uint types for UBOs/SSBOs but2445* would then store them to a local variable as bool. Work around2446* the issue by doing an implicit conversion.2447*2448* https://github.com/KhronosGroup/glslang/issues/1702449* https://bugs.freedesktop.org/show_bug.cgi?id=1044242450*/2451vtn_warn("OpStore of value of type OpTypeInt to a pointer to type "2452"OpTypeBool. Doing an implicit conversion to work around "2453"the problem.");2454struct vtn_ssa_value *bool_ssa =2455vtn_create_ssa_value(b, dest->type->type);2456bool_ssa->def = nir_i2b(&b->nb, vtn_ssa_value(b, w[2])->def);2457vtn_variable_store(b, bool_ssa, dest, 0);2458break;2459}24602461vtn_assert_types_equal(b, opcode, dest_val->type->deref, src_val->type);24622463unsigned idx = 3, alignment;2464SpvMemoryAccessMask access;2465SpvScope scope;2466vtn_get_mem_operands(b, w, count, &idx, &access, &alignment, &scope, NULL);2467dest = vtn_align_pointer(b, dest, alignment);24682469struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);2470vtn_variable_store(b, src, dest, spv_access_to_gl_access(access));24712472vtn_emit_make_available_barrier(b, access, scope, dest->mode);2473break;2474}24752476case SpvOpArrayLength: {2477struct vtn_pointer *ptr =2478vtn_value(b, w[3], vtn_value_type_pointer)->pointer;2479const uint32_t field = w[4];24802481vtn_fail_if(ptr->type->base_type != vtn_base_type_struct,2482"OpArrayLength must take a pointer to a structure type");2483vtn_fail_if(field != ptr->type->length - 1 ||2484ptr->type->members[field]->base_type != vtn_base_type_array,2485"OpArrayLength must reference the last memeber of the "2486"structure and that must be an array");24872488if (b->options->use_deref_buffer_array_length) {2489struct vtn_access_chain chain = {2490.length = 1,2491.link = {2492{ .mode = vtn_access_mode_literal, .id = field },2493}2494};2495struct vtn_pointer *array = vtn_pointer_dereference(b, ptr, &chain);24962497nir_ssa_def *array_length =2498nir_build_deref_buffer_array_length(&b->nb, 32,2499vtn_pointer_to_ssa(b, array),2500.access=ptr->access | ptr->type->access);25012502vtn_push_nir_ssa(b, w[2], array_length);2503} else {2504const uint32_t offset = ptr->type->offsets[field];2505const uint32_t stride = ptr->type->members[field]->stride;25062507if (!ptr->block_index) {2508struct vtn_access_chain chain = {2509.length = 0,2510};2511ptr = vtn_pointer_dereference(b, ptr, &chain);2512vtn_assert(ptr->block_index);2513}25142515nir_ssa_def *buf_size = nir_get_ssbo_size(&b->nb, ptr->block_index,2516.access=ptr->access | ptr->type->access);25172518/* array_length = max(buffer_size - offset, 0) / stride */2519nir_ssa_def *array_length =2520nir_idiv(&b->nb,2521nir_imax(&b->nb,2522nir_isub(&b->nb,2523buf_size,2524nir_imm_int(&b->nb, offset)),2525nir_imm_int(&b->nb, 0u)),2526nir_imm_int(&b->nb, stride));25272528vtn_push_nir_ssa(b, w[2], array_length);2529}2530break;2531}25322533case SpvOpConvertPtrToU: {2534struct vtn_type *u_type = vtn_get_type(b, w[1]);2535struct vtn_type *ptr_type = vtn_get_value_type(b, w[3]);25362537vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer ||2538ptr_type->type == NULL,2539"OpConvertPtrToU can only be used on physical pointers");25402541vtn_fail_if(u_type->base_type != vtn_base_type_vector &&2542u_type->base_type != vtn_base_type_scalar,2543"OpConvertPtrToU can only be used to cast to a vector or "2544"scalar type");25452546/* The pointer will be converted to an SSA value automatically */2547nir_ssa_def *ptr = vtn_get_nir_ssa(b, w[3]);2548nir_ssa_def *u = nir_sloppy_bitcast(&b->nb, ptr, u_type->type);2549vtn_push_nir_ssa(b, w[2], u);2550break;2551}25522553case SpvOpConvertUToPtr: {2554struct vtn_type *ptr_type = vtn_get_type(b, w[1]);2555struct vtn_type *u_type = vtn_get_value_type(b, w[3]);25562557vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer ||2558ptr_type->type == NULL,2559"OpConvertUToPtr can only be used on physical pointers");25602561vtn_fail_if(u_type->base_type != vtn_base_type_vector &&2562u_type->base_type != vtn_base_type_scalar,2563"OpConvertUToPtr can only be used to cast from a vector or "2564"scalar type");25652566nir_ssa_def *u = vtn_get_nir_ssa(b, w[3]);2567nir_ssa_def *ptr = nir_sloppy_bitcast(&b->nb, u, ptr_type->type);2568vtn_push_pointer(b, w[2], vtn_pointer_from_ssa(b, ptr, ptr_type));2569break;2570}25712572case SpvOpGenericCastToPtrExplicit: {2573struct vtn_type *dst_type = vtn_get_type(b, w[1]);2574struct vtn_type *src_type = vtn_get_value_type(b, w[3]);2575SpvStorageClass storage_class = w[4];25762577vtn_fail_if(dst_type->base_type != vtn_base_type_pointer ||2578dst_type->storage_class != storage_class,2579"Result type of an SpvOpGenericCastToPtrExplicit must be "2580"an OpTypePointer. Its Storage Class must match the "2581"storage class specified in the instruction");25822583vtn_fail_if(src_type->base_type != vtn_base_type_pointer ||2584src_type->deref->id != dst_type->deref->id,2585"Source pointer of an SpvOpGenericCastToPtrExplicit must "2586"have a type of OpTypePointer whose Type is the same as "2587"the Type of Result Type");25882589vtn_fail_if(src_type->storage_class != SpvStorageClassGeneric,2590"Source pointer of an SpvOpGenericCastToPtrExplicit must "2591"point to the Generic Storage Class.");25922593vtn_fail_if(storage_class != SpvStorageClassWorkgroup &&2594storage_class != SpvStorageClassCrossWorkgroup &&2595storage_class != SpvStorageClassFunction,2596"Storage must be one of the following literal values from "2597"Storage Class: Workgroup, CrossWorkgroup, or Function.");25982599nir_deref_instr *src_deref = vtn_nir_deref(b, w[3]);26002601nir_variable_mode nir_mode;2602enum vtn_variable_mode mode =2603vtn_storage_class_to_mode(b, storage_class, dst_type->deref, &nir_mode);2604nir_address_format addr_format = vtn_mode_to_address_format(b, mode);26052606nir_ssa_def *null_value =2607nir_build_imm(&b->nb, nir_address_format_num_components(addr_format),2608nir_address_format_bit_size(addr_format),2609nir_address_format_null_value(addr_format));26102611nir_ssa_def *valid = nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa, nir_mode);2612vtn_push_nir_ssa(b, w[2], nir_bcsel(&b->nb, valid,2613&src_deref->dest.ssa,2614null_value));2615break;2616}26172618case SpvOpGenericPtrMemSemantics: {2619struct vtn_type *dst_type = vtn_get_type(b, w[1]);2620struct vtn_type *src_type = vtn_get_value_type(b, w[3]);26212622vtn_fail_if(dst_type->base_type != vtn_base_type_scalar ||2623dst_type->type != glsl_uint_type(),2624"Result type of an SpvOpGenericPtrMemSemantics must be "2625"an OpTypeInt with 32-bit Width and 0 Signedness.");26262627vtn_fail_if(src_type->base_type != vtn_base_type_pointer ||2628src_type->storage_class != SpvStorageClassGeneric,2629"Source pointer of an SpvOpGenericPtrMemSemantics must "2630"point to the Generic Storage Class");26312632nir_deref_instr *src_deref = vtn_nir_deref(b, w[3]);26332634nir_ssa_def *global_bit =2635nir_bcsel(&b->nb, nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa,2636nir_var_mem_global),2637nir_imm_int(&b->nb, SpvMemorySemanticsCrossWorkgroupMemoryMask),2638nir_imm_int(&b->nb, 0));26392640nir_ssa_def *shared_bit =2641nir_bcsel(&b->nb, nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa,2642nir_var_mem_shared),2643nir_imm_int(&b->nb, SpvMemorySemanticsWorkgroupMemoryMask),2644nir_imm_int(&b->nb, 0));26452646vtn_push_nir_ssa(b, w[2], nir_iand(&b->nb, global_bit, shared_bit));2647break;2648}26492650case SpvOpSubgroupBlockReadINTEL: {2651struct vtn_type *res_type = vtn_get_type(b, w[1]);2652nir_deref_instr *src = vtn_nir_deref(b, w[3]);26532654nir_intrinsic_instr *load =2655nir_intrinsic_instr_create(b->nb.shader,2656nir_intrinsic_load_deref_block_intel);2657load->src[0] = nir_src_for_ssa(&src->dest.ssa);2658nir_ssa_dest_init_for_type(&load->instr, &load->dest,2659res_type->type, NULL);2660load->num_components = load->dest.ssa.num_components;2661nir_builder_instr_insert(&b->nb, &load->instr);26622663vtn_push_nir_ssa(b, w[2], &load->dest.ssa);2664break;2665}26662667case SpvOpSubgroupBlockWriteINTEL: {2668nir_deref_instr *dest = vtn_nir_deref(b, w[1]);2669nir_ssa_def *data = vtn_ssa_value(b, w[2])->def;26702671nir_intrinsic_instr *store =2672nir_intrinsic_instr_create(b->nb.shader,2673nir_intrinsic_store_deref_block_intel);2674store->src[0] = nir_src_for_ssa(&dest->dest.ssa);2675store->src[1] = nir_src_for_ssa(data);2676store->num_components = data->num_components;2677nir_builder_instr_insert(&b->nb, &store->instr);2678break;2679}26802681case SpvOpConvertUToAccelerationStructureKHR: {2682struct vtn_type *as_type = vtn_get_type(b, w[1]);2683struct vtn_type *u_type = vtn_get_value_type(b, w[3]);2684vtn_fail_if(!((u_type->base_type == vtn_base_type_vector &&2685u_type->type == glsl_vector_type(GLSL_TYPE_UINT, 2)) ||2686(u_type->base_type == vtn_base_type_scalar &&2687u_type->type == glsl_uint64_t_type())),2688"OpConvertUToAccelerationStructure may only be used to "2689"cast from a 64-bit scalar integer or a 2-component vector "2690"of 32-bit integers");2691vtn_fail_if(as_type->base_type != vtn_base_type_accel_struct,2692"The result type of an OpConvertUToAccelerationStructure "2693"must be OpTypeAccelerationStructure");26942695nir_ssa_def *u = vtn_get_nir_ssa(b, w[3]);2696vtn_push_nir_ssa(b, w[2], nir_sloppy_bitcast(&b->nb, u, as_type->type));2697break;2698}26992700default:2701vtn_fail_with_opcode("Unhandled opcode", opcode);2702}2703}270427052706