1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Jason Ekstrand (jason@jlekstrand.net) 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "vtn_private.h" 29bf215546Sopenharmony_ci#include "spirv_info.h" 30bf215546Sopenharmony_ci#include "nir_deref.h" 31bf215546Sopenharmony_ci#include <vulkan/vulkan_core.h> 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_cistatic struct vtn_pointer* 34bf215546Sopenharmony_civtn_align_pointer(struct vtn_builder *b, struct vtn_pointer *ptr, 35bf215546Sopenharmony_ci unsigned alignment) 36bf215546Sopenharmony_ci{ 37bf215546Sopenharmony_ci if (alignment == 0) 38bf215546Sopenharmony_ci return ptr; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci if (!util_is_power_of_two_nonzero(alignment)) { 41bf215546Sopenharmony_ci vtn_warn("Provided alignment is not a power of two"); 42bf215546Sopenharmony_ci alignment = 1 << (ffs(alignment) - 1); 43bf215546Sopenharmony_ci } 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci /* If this pointer doesn't have a deref, bail. This either means we're 46bf215546Sopenharmony_ci * using the old offset+alignment pointers which don't support carrying 47bf215546Sopenharmony_ci * alignment information or we're a pointer that is below the block 48bf215546Sopenharmony_ci * boundary in our access chain in which case alignment is meaningless. 49bf215546Sopenharmony_ci */ 50bf215546Sopenharmony_ci if (ptr->deref == NULL) 51bf215546Sopenharmony_ci return ptr; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci /* Ignore alignment information on logical pointers. This way, we don't 54bf215546Sopenharmony_ci * trip up drivers with unnecessary casts. 55bf215546Sopenharmony_ci */ 56bf215546Sopenharmony_ci nir_address_format addr_format = vtn_mode_to_address_format(b, ptr->mode); 57bf215546Sopenharmony_ci if (addr_format == nir_address_format_logical) 58bf215546Sopenharmony_ci return ptr; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci struct vtn_pointer *copy = ralloc(b, struct vtn_pointer); 61bf215546Sopenharmony_ci *copy = *ptr; 62bf215546Sopenharmony_ci copy->deref = nir_alignment_deref_cast(&b->nb, ptr->deref, alignment, 0); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci return copy; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic void 68bf215546Sopenharmony_ciptr_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, 69bf215546Sopenharmony_ci const struct vtn_decoration *dec, void *void_ptr) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci struct vtn_pointer *ptr = void_ptr; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci switch (dec->decoration) { 74bf215546Sopenharmony_ci case SpvDecorationNonUniformEXT: 75bf215546Sopenharmony_ci ptr->access |= ACCESS_NON_UNIFORM; 76bf215546Sopenharmony_ci break; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci default: 79bf215546Sopenharmony_ci break; 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistruct access_align { 84bf215546Sopenharmony_ci enum gl_access_qualifier access; 85bf215546Sopenharmony_ci uint32_t alignment; 86bf215546Sopenharmony_ci}; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic void 89bf215546Sopenharmony_ciaccess_align_cb(struct vtn_builder *b, struct vtn_value *val, int member, 90bf215546Sopenharmony_ci const struct vtn_decoration *dec, void *void_ptr) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct access_align *aa = void_ptr; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci switch (dec->decoration) { 95bf215546Sopenharmony_ci case SpvDecorationAlignment: 96bf215546Sopenharmony_ci aa->alignment = dec->operands[0]; 97bf215546Sopenharmony_ci break; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci case SpvDecorationNonUniformEXT: 100bf215546Sopenharmony_ci aa->access |= ACCESS_NON_UNIFORM; 101bf215546Sopenharmony_ci break; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci default: 104bf215546Sopenharmony_ci break; 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic struct vtn_pointer* 109bf215546Sopenharmony_civtn_decorate_pointer(struct vtn_builder *b, struct vtn_value *val, 110bf215546Sopenharmony_ci struct vtn_pointer *ptr) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci struct access_align aa = { 0, }; 113bf215546Sopenharmony_ci vtn_foreach_decoration(b, val, access_align_cb, &aa); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci ptr = vtn_align_pointer(b, ptr, aa.alignment); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci /* If we're adding access flags, make a copy of the pointer. We could 118bf215546Sopenharmony_ci * probably just OR them in without doing so but this prevents us from 119bf215546Sopenharmony_ci * leaking them any further than actually specified in the SPIR-V. 120bf215546Sopenharmony_ci */ 121bf215546Sopenharmony_ci if (aa.access & ~ptr->access) { 122bf215546Sopenharmony_ci struct vtn_pointer *copy = ralloc(b, struct vtn_pointer); 123bf215546Sopenharmony_ci *copy = *ptr; 124bf215546Sopenharmony_ci copy->access |= aa.access; 125bf215546Sopenharmony_ci return copy; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci return ptr; 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistruct vtn_value * 132bf215546Sopenharmony_civtn_push_pointer(struct vtn_builder *b, uint32_t value_id, 133bf215546Sopenharmony_ci struct vtn_pointer *ptr) 134bf215546Sopenharmony_ci{ 135bf215546Sopenharmony_ci struct vtn_value *val = vtn_push_value(b, value_id, vtn_value_type_pointer); 136bf215546Sopenharmony_ci val->pointer = vtn_decorate_pointer(b, val, ptr); 137bf215546Sopenharmony_ci return val; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_civoid 141bf215546Sopenharmony_civtn_copy_value(struct vtn_builder *b, uint32_t src_value_id, 142bf215546Sopenharmony_ci uint32_t dst_value_id) 143bf215546Sopenharmony_ci{ 144bf215546Sopenharmony_ci struct vtn_value *src = vtn_untyped_value(b, src_value_id); 145bf215546Sopenharmony_ci struct vtn_value *dst = vtn_untyped_value(b, dst_value_id); 146bf215546Sopenharmony_ci struct vtn_value src_copy = *src; 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci vtn_fail_if(dst->value_type != vtn_value_type_invalid, 149bf215546Sopenharmony_ci "SPIR-V id %u has already been written by another instruction", 150bf215546Sopenharmony_ci dst_value_id); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci vtn_fail_if(dst->type->id != src->type->id, 153bf215546Sopenharmony_ci "Result Type must equal Operand type"); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci src_copy.name = dst->name; 156bf215546Sopenharmony_ci src_copy.decoration = dst->decoration; 157bf215546Sopenharmony_ci src_copy.type = dst->type; 158bf215546Sopenharmony_ci *dst = src_copy; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci if (dst->value_type == vtn_value_type_pointer) 161bf215546Sopenharmony_ci dst->pointer = vtn_decorate_pointer(b, dst, dst->pointer); 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistatic struct vtn_access_chain * 165bf215546Sopenharmony_civtn_access_chain_create(struct vtn_builder *b, unsigned length) 166bf215546Sopenharmony_ci{ 167bf215546Sopenharmony_ci struct vtn_access_chain *chain; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /* Subtract 1 from the length since there's already one built in */ 170bf215546Sopenharmony_ci size_t size = sizeof(*chain) + 171bf215546Sopenharmony_ci (MAX2(length, 1) - 1) * sizeof(chain->link[0]); 172bf215546Sopenharmony_ci chain = rzalloc_size(b, size); 173bf215546Sopenharmony_ci chain->length = length; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci return chain; 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_cistatic bool 179bf215546Sopenharmony_civtn_mode_is_cross_invocation(struct vtn_builder *b, 180bf215546Sopenharmony_ci enum vtn_variable_mode mode) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci return mode == vtn_variable_mode_ssbo || 183bf215546Sopenharmony_ci mode == vtn_variable_mode_ubo || 184bf215546Sopenharmony_ci mode == vtn_variable_mode_phys_ssbo || 185bf215546Sopenharmony_ci mode == vtn_variable_mode_push_constant || 186bf215546Sopenharmony_ci mode == vtn_variable_mode_workgroup || 187bf215546Sopenharmony_ci mode == vtn_variable_mode_cross_workgroup; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic bool 191bf215546Sopenharmony_civtn_pointer_is_external_block(struct vtn_builder *b, 192bf215546Sopenharmony_ci struct vtn_pointer *ptr) 193bf215546Sopenharmony_ci{ 194bf215546Sopenharmony_ci return ptr->mode == vtn_variable_mode_ssbo || 195bf215546Sopenharmony_ci ptr->mode == vtn_variable_mode_ubo || 196bf215546Sopenharmony_ci ptr->mode == vtn_variable_mode_phys_ssbo; 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_cistatic nir_ssa_def * 200bf215546Sopenharmony_civtn_access_link_as_ssa(struct vtn_builder *b, struct vtn_access_link link, 201bf215546Sopenharmony_ci unsigned stride, unsigned bit_size) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci vtn_assert(stride > 0); 204bf215546Sopenharmony_ci if (link.mode == vtn_access_mode_literal) { 205bf215546Sopenharmony_ci return nir_imm_intN_t(&b->nb, link.id * stride, bit_size); 206bf215546Sopenharmony_ci } else { 207bf215546Sopenharmony_ci nir_ssa_def *ssa = vtn_ssa_value(b, link.id)->def; 208bf215546Sopenharmony_ci if (ssa->bit_size != bit_size) 209bf215546Sopenharmony_ci ssa = nir_i2i(&b->nb, ssa, bit_size); 210bf215546Sopenharmony_ci return nir_imul_imm(&b->nb, ssa, stride); 211bf215546Sopenharmony_ci } 212bf215546Sopenharmony_ci} 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_cistatic VkDescriptorType 215bf215546Sopenharmony_civk_desc_type_for_mode(struct vtn_builder *b, enum vtn_variable_mode mode) 216bf215546Sopenharmony_ci{ 217bf215546Sopenharmony_ci switch (mode) { 218bf215546Sopenharmony_ci case vtn_variable_mode_ubo: 219bf215546Sopenharmony_ci return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 220bf215546Sopenharmony_ci case vtn_variable_mode_ssbo: 221bf215546Sopenharmony_ci return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 222bf215546Sopenharmony_ci case vtn_variable_mode_accel_struct: 223bf215546Sopenharmony_ci return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; 224bf215546Sopenharmony_ci default: 225bf215546Sopenharmony_ci vtn_fail("Invalid mode for vulkan_resource_index"); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cistatic nir_ssa_def * 230bf215546Sopenharmony_civtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var, 231bf215546Sopenharmony_ci nir_ssa_def *desc_array_index) 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci vtn_assert(b->options->environment == NIR_SPIRV_VULKAN); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci if (!desc_array_index) 236bf215546Sopenharmony_ci desc_array_index = nir_imm_int(&b->nb, 0); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci if (b->vars_used_indirectly) { 239bf215546Sopenharmony_ci vtn_assert(var->var); 240bf215546Sopenharmony_ci _mesa_set_add(b->vars_used_indirectly, var->var); 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci nir_intrinsic_instr *instr = 244bf215546Sopenharmony_ci nir_intrinsic_instr_create(b->nb.shader, 245bf215546Sopenharmony_ci nir_intrinsic_vulkan_resource_index); 246bf215546Sopenharmony_ci instr->src[0] = nir_src_for_ssa(desc_array_index); 247bf215546Sopenharmony_ci nir_intrinsic_set_desc_set(instr, var->descriptor_set); 248bf215546Sopenharmony_ci nir_intrinsic_set_binding(instr, var->binding); 249bf215546Sopenharmony_ci nir_intrinsic_set_desc_type(instr, vk_desc_type_for_mode(b, var->mode)); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci nir_address_format addr_format = vtn_mode_to_address_format(b, var->mode); 252bf215546Sopenharmony_ci nir_ssa_dest_init(&instr->instr, &instr->dest, 253bf215546Sopenharmony_ci nir_address_format_num_components(addr_format), 254bf215546Sopenharmony_ci nir_address_format_bit_size(addr_format), NULL); 255bf215546Sopenharmony_ci instr->num_components = instr->dest.ssa.num_components; 256bf215546Sopenharmony_ci nir_builder_instr_insert(&b->nb, &instr->instr); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci return &instr->dest.ssa; 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_cistatic nir_ssa_def * 262bf215546Sopenharmony_civtn_resource_reindex(struct vtn_builder *b, enum vtn_variable_mode mode, 263bf215546Sopenharmony_ci nir_ssa_def *base_index, nir_ssa_def *offset_index) 264bf215546Sopenharmony_ci{ 265bf215546Sopenharmony_ci vtn_assert(b->options->environment == NIR_SPIRV_VULKAN); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci nir_intrinsic_instr *instr = 268bf215546Sopenharmony_ci nir_intrinsic_instr_create(b->nb.shader, 269bf215546Sopenharmony_ci nir_intrinsic_vulkan_resource_reindex); 270bf215546Sopenharmony_ci instr->src[0] = nir_src_for_ssa(base_index); 271bf215546Sopenharmony_ci instr->src[1] = nir_src_for_ssa(offset_index); 272bf215546Sopenharmony_ci nir_intrinsic_set_desc_type(instr, vk_desc_type_for_mode(b, mode)); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci nir_address_format addr_format = vtn_mode_to_address_format(b, mode); 275bf215546Sopenharmony_ci nir_ssa_dest_init(&instr->instr, &instr->dest, 276bf215546Sopenharmony_ci nir_address_format_num_components(addr_format), 277bf215546Sopenharmony_ci nir_address_format_bit_size(addr_format), NULL); 278bf215546Sopenharmony_ci instr->num_components = instr->dest.ssa.num_components; 279bf215546Sopenharmony_ci nir_builder_instr_insert(&b->nb, &instr->instr); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci return &instr->dest.ssa; 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_cistatic nir_ssa_def * 285bf215546Sopenharmony_civtn_descriptor_load(struct vtn_builder *b, enum vtn_variable_mode mode, 286bf215546Sopenharmony_ci nir_ssa_def *desc_index) 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_ci vtn_assert(b->options->environment == NIR_SPIRV_VULKAN); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci nir_intrinsic_instr *desc_load = 291bf215546Sopenharmony_ci nir_intrinsic_instr_create(b->nb.shader, 292bf215546Sopenharmony_ci nir_intrinsic_load_vulkan_descriptor); 293bf215546Sopenharmony_ci desc_load->src[0] = nir_src_for_ssa(desc_index); 294bf215546Sopenharmony_ci nir_intrinsic_set_desc_type(desc_load, vk_desc_type_for_mode(b, mode)); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci nir_address_format addr_format = vtn_mode_to_address_format(b, mode); 297bf215546Sopenharmony_ci nir_ssa_dest_init(&desc_load->instr, &desc_load->dest, 298bf215546Sopenharmony_ci nir_address_format_num_components(addr_format), 299bf215546Sopenharmony_ci nir_address_format_bit_size(addr_format), NULL); 300bf215546Sopenharmony_ci desc_load->num_components = desc_load->dest.ssa.num_components; 301bf215546Sopenharmony_ci nir_builder_instr_insert(&b->nb, &desc_load->instr); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci return &desc_load->dest.ssa; 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic struct vtn_pointer * 307bf215546Sopenharmony_civtn_pointer_dereference(struct vtn_builder *b, 308bf215546Sopenharmony_ci struct vtn_pointer *base, 309bf215546Sopenharmony_ci struct vtn_access_chain *deref_chain) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci struct vtn_type *type = base->type; 312bf215546Sopenharmony_ci enum gl_access_qualifier access = base->access | deref_chain->access; 313bf215546Sopenharmony_ci unsigned idx = 0; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci nir_deref_instr *tail; 316bf215546Sopenharmony_ci if (base->deref) { 317bf215546Sopenharmony_ci tail = base->deref; 318bf215546Sopenharmony_ci } else if (b->options->environment == NIR_SPIRV_VULKAN && 319bf215546Sopenharmony_ci (vtn_pointer_is_external_block(b, base) || 320bf215546Sopenharmony_ci base->mode == vtn_variable_mode_accel_struct)) { 321bf215546Sopenharmony_ci nir_ssa_def *block_index = base->block_index; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci /* We dereferencing an external block pointer. Correctness of this 324bf215546Sopenharmony_ci * operation relies on one particular line in the SPIR-V spec, section 325bf215546Sopenharmony_ci * entitled "Validation Rules for Shader Capabilities": 326bf215546Sopenharmony_ci * 327bf215546Sopenharmony_ci * "Block and BufferBlock decorations cannot decorate a structure 328bf215546Sopenharmony_ci * type that is nested at any level inside another structure type 329bf215546Sopenharmony_ci * decorated with Block or BufferBlock." 330bf215546Sopenharmony_ci * 331bf215546Sopenharmony_ci * This means that we can detect the point where we cross over from 332bf215546Sopenharmony_ci * descriptor indexing to buffer indexing by looking for the block 333bf215546Sopenharmony_ci * decorated struct type. Anything before the block decorated struct 334bf215546Sopenharmony_ci * type is a descriptor indexing operation and anything after the block 335bf215546Sopenharmony_ci * decorated struct is a buffer offset operation. 336bf215546Sopenharmony_ci */ 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci /* Figure out the descriptor array index if any 339bf215546Sopenharmony_ci * 340bf215546Sopenharmony_ci * Some of the Vulkan CTS tests with hand-rolled SPIR-V have been known 341bf215546Sopenharmony_ci * to forget the Block or BufferBlock decoration from time to time. 342bf215546Sopenharmony_ci * It's more robust if we check for both !block_index and for the type 343bf215546Sopenharmony_ci * to contain a block. This way there's a decent chance that arrays of 344bf215546Sopenharmony_ci * UBOs/SSBOs will work correctly even if variable pointers are 345bf215546Sopenharmony_ci * completley toast. 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_ci nir_ssa_def *desc_arr_idx = NULL; 348bf215546Sopenharmony_ci if (!block_index || vtn_type_contains_block(b, type) || 349bf215546Sopenharmony_ci base->mode == vtn_variable_mode_accel_struct) { 350bf215546Sopenharmony_ci /* If our type contains a block, then we're still outside the block 351bf215546Sopenharmony_ci * and we need to process enough levels of dereferences to get inside 352bf215546Sopenharmony_ci * of it. Same applies to acceleration structures. 353bf215546Sopenharmony_ci */ 354bf215546Sopenharmony_ci if (deref_chain->ptr_as_array) { 355bf215546Sopenharmony_ci unsigned aoa_size = glsl_get_aoa_size(type->type); 356bf215546Sopenharmony_ci desc_arr_idx = vtn_access_link_as_ssa(b, deref_chain->link[idx], 357bf215546Sopenharmony_ci MAX2(aoa_size, 1), 32); 358bf215546Sopenharmony_ci idx++; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci for (; idx < deref_chain->length; idx++) { 362bf215546Sopenharmony_ci if (type->base_type != vtn_base_type_array) { 363bf215546Sopenharmony_ci vtn_assert(type->base_type == vtn_base_type_struct); 364bf215546Sopenharmony_ci break; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci unsigned aoa_size = glsl_get_aoa_size(type->array_element->type); 368bf215546Sopenharmony_ci nir_ssa_def *arr_offset = 369bf215546Sopenharmony_ci vtn_access_link_as_ssa(b, deref_chain->link[idx], 370bf215546Sopenharmony_ci MAX2(aoa_size, 1), 32); 371bf215546Sopenharmony_ci if (desc_arr_idx) 372bf215546Sopenharmony_ci desc_arr_idx = nir_iadd(&b->nb, desc_arr_idx, arr_offset); 373bf215546Sopenharmony_ci else 374bf215546Sopenharmony_ci desc_arr_idx = arr_offset; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci type = type->array_element; 377bf215546Sopenharmony_ci access |= type->access; 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci if (!block_index) { 382bf215546Sopenharmony_ci vtn_assert(base->var && base->type); 383bf215546Sopenharmony_ci block_index = vtn_variable_resource_index(b, base->var, desc_arr_idx); 384bf215546Sopenharmony_ci } else if (desc_arr_idx) { 385bf215546Sopenharmony_ci block_index = vtn_resource_reindex(b, base->mode, 386bf215546Sopenharmony_ci block_index, desc_arr_idx); 387bf215546Sopenharmony_ci } 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci if (idx == deref_chain->length) { 390bf215546Sopenharmony_ci /* The entire deref was consumed in finding the block index. Return 391bf215546Sopenharmony_ci * a pointer which just has a block index and a later access chain 392bf215546Sopenharmony_ci * will dereference deeper. 393bf215546Sopenharmony_ci */ 394bf215546Sopenharmony_ci struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer); 395bf215546Sopenharmony_ci ptr->mode = base->mode; 396bf215546Sopenharmony_ci ptr->type = type; 397bf215546Sopenharmony_ci ptr->block_index = block_index; 398bf215546Sopenharmony_ci ptr->access = access; 399bf215546Sopenharmony_ci return ptr; 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci /* If we got here, there's more access chain to handle and we have the 403bf215546Sopenharmony_ci * final block index. Insert a descriptor load and cast to a deref to 404bf215546Sopenharmony_ci * start the deref chain. 405bf215546Sopenharmony_ci */ 406bf215546Sopenharmony_ci nir_ssa_def *desc = vtn_descriptor_load(b, base->mode, block_index); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci assert(base->mode == vtn_variable_mode_ssbo || 409bf215546Sopenharmony_ci base->mode == vtn_variable_mode_ubo); 410bf215546Sopenharmony_ci nir_variable_mode nir_mode = 411bf215546Sopenharmony_ci base->mode == vtn_variable_mode_ssbo ? nir_var_mem_ssbo : nir_var_mem_ubo; 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci tail = nir_build_deref_cast(&b->nb, desc, nir_mode, 414bf215546Sopenharmony_ci vtn_type_get_nir_type(b, type, base->mode), 415bf215546Sopenharmony_ci base->ptr_type->stride); 416bf215546Sopenharmony_ci } else if (base->mode == vtn_variable_mode_shader_record) { 417bf215546Sopenharmony_ci /* For ShaderRecordBufferKHR variables, we don't have a nir_variable. 418bf215546Sopenharmony_ci * It's just a fancy handle around a pointer to the shader record for 419bf215546Sopenharmony_ci * the current shader. 420bf215546Sopenharmony_ci */ 421bf215546Sopenharmony_ci tail = nir_build_deref_cast(&b->nb, nir_load_shader_record_ptr(&b->nb), 422bf215546Sopenharmony_ci nir_var_mem_constant, 423bf215546Sopenharmony_ci vtn_type_get_nir_type(b, base->type, 424bf215546Sopenharmony_ci base->mode), 425bf215546Sopenharmony_ci 0 /* ptr_as_array stride */); 426bf215546Sopenharmony_ci } else { 427bf215546Sopenharmony_ci assert(base->var && base->var->var); 428bf215546Sopenharmony_ci tail = nir_build_deref_var(&b->nb, base->var->var); 429bf215546Sopenharmony_ci if (base->ptr_type && base->ptr_type->type) { 430bf215546Sopenharmony_ci tail->dest.ssa.num_components = 431bf215546Sopenharmony_ci glsl_get_vector_elements(base->ptr_type->type); 432bf215546Sopenharmony_ci tail->dest.ssa.bit_size = glsl_get_bit_size(base->ptr_type->type); 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci if (idx == 0 && deref_chain->ptr_as_array) { 437bf215546Sopenharmony_ci /* We start with a deref cast to get the stride. Hopefully, we'll be 438bf215546Sopenharmony_ci * able to delete that cast eventually. 439bf215546Sopenharmony_ci */ 440bf215546Sopenharmony_ci tail = nir_build_deref_cast(&b->nb, &tail->dest.ssa, tail->modes, 441bf215546Sopenharmony_ci tail->type, base->ptr_type->stride); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci nir_ssa_def *index = vtn_access_link_as_ssa(b, deref_chain->link[0], 1, 444bf215546Sopenharmony_ci tail->dest.ssa.bit_size); 445bf215546Sopenharmony_ci tail = nir_build_deref_ptr_as_array(&b->nb, tail, index); 446bf215546Sopenharmony_ci idx++; 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci for (; idx < deref_chain->length; idx++) { 450bf215546Sopenharmony_ci if (glsl_type_is_struct_or_ifc(type->type)) { 451bf215546Sopenharmony_ci vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal); 452bf215546Sopenharmony_ci unsigned field = deref_chain->link[idx].id; 453bf215546Sopenharmony_ci tail = nir_build_deref_struct(&b->nb, tail, field); 454bf215546Sopenharmony_ci type = type->members[field]; 455bf215546Sopenharmony_ci } else { 456bf215546Sopenharmony_ci nir_ssa_def *arr_index = 457bf215546Sopenharmony_ci vtn_access_link_as_ssa(b, deref_chain->link[idx], 1, 458bf215546Sopenharmony_ci tail->dest.ssa.bit_size); 459bf215546Sopenharmony_ci tail = nir_build_deref_array(&b->nb, tail, arr_index); 460bf215546Sopenharmony_ci type = type->array_element; 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci tail->arr.in_bounds = deref_chain->in_bounds; 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci access |= type->access; 465bf215546Sopenharmony_ci } 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer); 468bf215546Sopenharmony_ci ptr->mode = base->mode; 469bf215546Sopenharmony_ci ptr->type = type; 470bf215546Sopenharmony_ci ptr->var = base->var; 471bf215546Sopenharmony_ci ptr->deref = tail; 472bf215546Sopenharmony_ci ptr->access = access; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci return ptr; 475bf215546Sopenharmony_ci} 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_cinir_deref_instr * 478bf215546Sopenharmony_civtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr) 479bf215546Sopenharmony_ci{ 480bf215546Sopenharmony_ci if (!ptr->deref) { 481bf215546Sopenharmony_ci struct vtn_access_chain chain = { 482bf215546Sopenharmony_ci .length = 0, 483bf215546Sopenharmony_ci }; 484bf215546Sopenharmony_ci ptr = vtn_pointer_dereference(b, ptr, &chain); 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci return ptr->deref; 488bf215546Sopenharmony_ci} 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_cistatic void 491bf215546Sopenharmony_ci_vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_instr *deref, 492bf215546Sopenharmony_ci struct vtn_ssa_value *inout, 493bf215546Sopenharmony_ci enum gl_access_qualifier access) 494bf215546Sopenharmony_ci{ 495bf215546Sopenharmony_ci if (glsl_type_is_vector_or_scalar(deref->type)) { 496bf215546Sopenharmony_ci if (load) { 497bf215546Sopenharmony_ci inout->def = nir_load_deref_with_access(&b->nb, deref, access); 498bf215546Sopenharmony_ci } else { 499bf215546Sopenharmony_ci nir_store_deref_with_access(&b->nb, deref, inout->def, ~0, access); 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci } else if (glsl_type_is_array(deref->type) || 502bf215546Sopenharmony_ci glsl_type_is_matrix(deref->type)) { 503bf215546Sopenharmony_ci unsigned elems = glsl_get_length(deref->type); 504bf215546Sopenharmony_ci for (unsigned i = 0; i < elems; i++) { 505bf215546Sopenharmony_ci nir_deref_instr *child = 506bf215546Sopenharmony_ci nir_build_deref_array_imm(&b->nb, deref, i); 507bf215546Sopenharmony_ci _vtn_local_load_store(b, load, child, inout->elems[i], access); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci } else { 510bf215546Sopenharmony_ci vtn_assert(glsl_type_is_struct_or_ifc(deref->type)); 511bf215546Sopenharmony_ci unsigned elems = glsl_get_length(deref->type); 512bf215546Sopenharmony_ci for (unsigned i = 0; i < elems; i++) { 513bf215546Sopenharmony_ci nir_deref_instr *child = nir_build_deref_struct(&b->nb, deref, i); 514bf215546Sopenharmony_ci _vtn_local_load_store(b, load, child, inout->elems[i], access); 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_cinir_deref_instr * 520bf215546Sopenharmony_civtn_nir_deref(struct vtn_builder *b, uint32_t id) 521bf215546Sopenharmony_ci{ 522bf215546Sopenharmony_ci struct vtn_pointer *ptr = vtn_pointer(b, id); 523bf215546Sopenharmony_ci return vtn_pointer_to_deref(b, ptr); 524bf215546Sopenharmony_ci} 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci/* 527bf215546Sopenharmony_ci * Gets the NIR-level deref tail, which may have as a child an array deref 528bf215546Sopenharmony_ci * selecting which component due to OpAccessChain supporting per-component 529bf215546Sopenharmony_ci * indexing in SPIR-V. 530bf215546Sopenharmony_ci */ 531bf215546Sopenharmony_cistatic nir_deref_instr * 532bf215546Sopenharmony_ciget_deref_tail(nir_deref_instr *deref) 533bf215546Sopenharmony_ci{ 534bf215546Sopenharmony_ci if (deref->deref_type != nir_deref_type_array) 535bf215546Sopenharmony_ci return deref; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci nir_deref_instr *parent = 538bf215546Sopenharmony_ci nir_instr_as_deref(deref->parent.ssa->parent_instr); 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci if (glsl_type_is_vector(parent->type)) 541bf215546Sopenharmony_ci return parent; 542bf215546Sopenharmony_ci else 543bf215546Sopenharmony_ci return deref; 544bf215546Sopenharmony_ci} 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_cistruct vtn_ssa_value * 547bf215546Sopenharmony_civtn_local_load(struct vtn_builder *b, nir_deref_instr *src, 548bf215546Sopenharmony_ci enum gl_access_qualifier access) 549bf215546Sopenharmony_ci{ 550bf215546Sopenharmony_ci nir_deref_instr *src_tail = get_deref_tail(src); 551bf215546Sopenharmony_ci struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type); 552bf215546Sopenharmony_ci _vtn_local_load_store(b, true, src_tail, val, access); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci if (src_tail != src) { 555bf215546Sopenharmony_ci val->type = src->type; 556bf215546Sopenharmony_ci val->def = nir_vector_extract(&b->nb, val->def, src->arr.index.ssa); 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci return val; 560bf215546Sopenharmony_ci} 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_civoid 563bf215546Sopenharmony_civtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src, 564bf215546Sopenharmony_ci nir_deref_instr *dest, enum gl_access_qualifier access) 565bf215546Sopenharmony_ci{ 566bf215546Sopenharmony_ci nir_deref_instr *dest_tail = get_deref_tail(dest); 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci if (dest_tail != dest) { 569bf215546Sopenharmony_ci struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type); 570bf215546Sopenharmony_ci _vtn_local_load_store(b, true, dest_tail, val, access); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci val->def = nir_vector_insert(&b->nb, val->def, src->def, 573bf215546Sopenharmony_ci dest->arr.index.ssa); 574bf215546Sopenharmony_ci _vtn_local_load_store(b, false, dest_tail, val, access); 575bf215546Sopenharmony_ci } else { 576bf215546Sopenharmony_ci _vtn_local_load_store(b, false, dest_tail, src, access); 577bf215546Sopenharmony_ci } 578bf215546Sopenharmony_ci} 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_cistatic nir_ssa_def * 581bf215546Sopenharmony_civtn_pointer_to_descriptor(struct vtn_builder *b, struct vtn_pointer *ptr) 582bf215546Sopenharmony_ci{ 583bf215546Sopenharmony_ci assert(ptr->mode == vtn_variable_mode_accel_struct); 584bf215546Sopenharmony_ci if (!ptr->block_index) { 585bf215546Sopenharmony_ci struct vtn_access_chain chain = { 586bf215546Sopenharmony_ci .length = 0, 587bf215546Sopenharmony_ci }; 588bf215546Sopenharmony_ci ptr = vtn_pointer_dereference(b, ptr, &chain); 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci vtn_assert(ptr->deref == NULL && ptr->block_index != NULL); 592bf215546Sopenharmony_ci return vtn_descriptor_load(b, ptr->mode, ptr->block_index); 593bf215546Sopenharmony_ci} 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_cistatic void 596bf215546Sopenharmony_ci_vtn_variable_load_store(struct vtn_builder *b, bool load, 597bf215546Sopenharmony_ci struct vtn_pointer *ptr, 598bf215546Sopenharmony_ci enum gl_access_qualifier access, 599bf215546Sopenharmony_ci struct vtn_ssa_value **inout) 600bf215546Sopenharmony_ci{ 601bf215546Sopenharmony_ci if (ptr->mode == vtn_variable_mode_uniform || 602bf215546Sopenharmony_ci ptr->mode == vtn_variable_mode_image) { 603bf215546Sopenharmony_ci if (ptr->type->base_type == vtn_base_type_image || 604bf215546Sopenharmony_ci ptr->type->base_type == vtn_base_type_sampler) { 605bf215546Sopenharmony_ci /* See also our handling of OpTypeSampler and OpTypeImage */ 606bf215546Sopenharmony_ci vtn_assert(load); 607bf215546Sopenharmony_ci (*inout)->def = vtn_pointer_to_ssa(b, ptr); 608bf215546Sopenharmony_ci return; 609bf215546Sopenharmony_ci } else if (ptr->type->base_type == vtn_base_type_sampled_image) { 610bf215546Sopenharmony_ci /* See also our handling of OpTypeSampledImage */ 611bf215546Sopenharmony_ci vtn_assert(load); 612bf215546Sopenharmony_ci struct vtn_sampled_image si = { 613bf215546Sopenharmony_ci .image = vtn_pointer_to_deref(b, ptr), 614bf215546Sopenharmony_ci .sampler = vtn_pointer_to_deref(b, ptr), 615bf215546Sopenharmony_ci }; 616bf215546Sopenharmony_ci (*inout)->def = vtn_sampled_image_to_nir_ssa(b, si); 617bf215546Sopenharmony_ci return; 618bf215546Sopenharmony_ci } 619bf215546Sopenharmony_ci } else if (ptr->mode == vtn_variable_mode_accel_struct) { 620bf215546Sopenharmony_ci vtn_assert(load); 621bf215546Sopenharmony_ci (*inout)->def = vtn_pointer_to_descriptor(b, ptr); 622bf215546Sopenharmony_ci return; 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci enum glsl_base_type base_type = glsl_get_base_type(ptr->type->type); 626bf215546Sopenharmony_ci switch (base_type) { 627bf215546Sopenharmony_ci case GLSL_TYPE_UINT: 628bf215546Sopenharmony_ci case GLSL_TYPE_INT: 629bf215546Sopenharmony_ci case GLSL_TYPE_UINT16: 630bf215546Sopenharmony_ci case GLSL_TYPE_INT16: 631bf215546Sopenharmony_ci case GLSL_TYPE_UINT8: 632bf215546Sopenharmony_ci case GLSL_TYPE_INT8: 633bf215546Sopenharmony_ci case GLSL_TYPE_UINT64: 634bf215546Sopenharmony_ci case GLSL_TYPE_INT64: 635bf215546Sopenharmony_ci case GLSL_TYPE_FLOAT: 636bf215546Sopenharmony_ci case GLSL_TYPE_FLOAT16: 637bf215546Sopenharmony_ci case GLSL_TYPE_BOOL: 638bf215546Sopenharmony_ci case GLSL_TYPE_DOUBLE: 639bf215546Sopenharmony_ci if (glsl_type_is_vector_or_scalar(ptr->type->type)) { 640bf215546Sopenharmony_ci /* We hit a vector or scalar; go ahead and emit the load[s] */ 641bf215546Sopenharmony_ci nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr); 642bf215546Sopenharmony_ci if (vtn_mode_is_cross_invocation(b, ptr->mode)) { 643bf215546Sopenharmony_ci /* If it's cross-invocation, we call nir_load/store_deref 644bf215546Sopenharmony_ci * directly. The vtn_local_load/store helpers are too clever and 645bf215546Sopenharmony_ci * do magic to avoid array derefs of vectors. That magic is both 646bf215546Sopenharmony_ci * less efficient than the direct load/store and, in the case of 647bf215546Sopenharmony_ci * stores, is broken because it creates a race condition if two 648bf215546Sopenharmony_ci * threads are writing to different components of the same vector 649bf215546Sopenharmony_ci * due to the load+insert+store it uses to emulate the array 650bf215546Sopenharmony_ci * deref. 651bf215546Sopenharmony_ci */ 652bf215546Sopenharmony_ci if (load) { 653bf215546Sopenharmony_ci (*inout)->def = nir_load_deref_with_access(&b->nb, deref, 654bf215546Sopenharmony_ci ptr->type->access | access); 655bf215546Sopenharmony_ci } else { 656bf215546Sopenharmony_ci nir_store_deref_with_access(&b->nb, deref, (*inout)->def, ~0, 657bf215546Sopenharmony_ci ptr->type->access | access); 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci } else { 660bf215546Sopenharmony_ci if (load) { 661bf215546Sopenharmony_ci *inout = vtn_local_load(b, deref, ptr->type->access | access); 662bf215546Sopenharmony_ci } else { 663bf215546Sopenharmony_ci vtn_local_store(b, *inout, deref, ptr->type->access | access); 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci return; 667bf215546Sopenharmony_ci } 668bf215546Sopenharmony_ci FALLTHROUGH; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci case GLSL_TYPE_INTERFACE: 671bf215546Sopenharmony_ci case GLSL_TYPE_ARRAY: 672bf215546Sopenharmony_ci case GLSL_TYPE_STRUCT: { 673bf215546Sopenharmony_ci unsigned elems = glsl_get_length(ptr->type->type); 674bf215546Sopenharmony_ci struct vtn_access_chain chain = { 675bf215546Sopenharmony_ci .length = 1, 676bf215546Sopenharmony_ci .link = { 677bf215546Sopenharmony_ci { .mode = vtn_access_mode_literal, }, 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci }; 680bf215546Sopenharmony_ci for (unsigned i = 0; i < elems; i++) { 681bf215546Sopenharmony_ci chain.link[0].id = i; 682bf215546Sopenharmony_ci struct vtn_pointer *elem = vtn_pointer_dereference(b, ptr, &chain); 683bf215546Sopenharmony_ci _vtn_variable_load_store(b, load, elem, ptr->type->access | access, 684bf215546Sopenharmony_ci &(*inout)->elems[i]); 685bf215546Sopenharmony_ci } 686bf215546Sopenharmony_ci return; 687bf215546Sopenharmony_ci } 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci default: 690bf215546Sopenharmony_ci vtn_fail("Invalid access chain type"); 691bf215546Sopenharmony_ci } 692bf215546Sopenharmony_ci} 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_cistruct vtn_ssa_value * 695bf215546Sopenharmony_civtn_variable_load(struct vtn_builder *b, struct vtn_pointer *src, 696bf215546Sopenharmony_ci enum gl_access_qualifier access) 697bf215546Sopenharmony_ci{ 698bf215546Sopenharmony_ci struct vtn_ssa_value *val = vtn_create_ssa_value(b, src->type->type); 699bf215546Sopenharmony_ci _vtn_variable_load_store(b, true, src, src->access | access, &val); 700bf215546Sopenharmony_ci return val; 701bf215546Sopenharmony_ci} 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_civoid 704bf215546Sopenharmony_civtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src, 705bf215546Sopenharmony_ci struct vtn_pointer *dest, enum gl_access_qualifier access) 706bf215546Sopenharmony_ci{ 707bf215546Sopenharmony_ci _vtn_variable_load_store(b, false, dest, dest->access | access, &src); 708bf215546Sopenharmony_ci} 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_cistatic void 711bf215546Sopenharmony_ci_vtn_variable_copy(struct vtn_builder *b, struct vtn_pointer *dest, 712bf215546Sopenharmony_ci struct vtn_pointer *src, enum gl_access_qualifier dest_access, 713bf215546Sopenharmony_ci enum gl_access_qualifier src_access) 714bf215546Sopenharmony_ci{ 715bf215546Sopenharmony_ci vtn_assert(glsl_get_bare_type(src->type->type) == 716bf215546Sopenharmony_ci glsl_get_bare_type(dest->type->type)); 717bf215546Sopenharmony_ci enum glsl_base_type base_type = glsl_get_base_type(src->type->type); 718bf215546Sopenharmony_ci switch (base_type) { 719bf215546Sopenharmony_ci case GLSL_TYPE_UINT: 720bf215546Sopenharmony_ci case GLSL_TYPE_INT: 721bf215546Sopenharmony_ci case GLSL_TYPE_UINT16: 722bf215546Sopenharmony_ci case GLSL_TYPE_INT16: 723bf215546Sopenharmony_ci case GLSL_TYPE_UINT8: 724bf215546Sopenharmony_ci case GLSL_TYPE_INT8: 725bf215546Sopenharmony_ci case GLSL_TYPE_UINT64: 726bf215546Sopenharmony_ci case GLSL_TYPE_INT64: 727bf215546Sopenharmony_ci case GLSL_TYPE_FLOAT: 728bf215546Sopenharmony_ci case GLSL_TYPE_FLOAT16: 729bf215546Sopenharmony_ci case GLSL_TYPE_DOUBLE: 730bf215546Sopenharmony_ci case GLSL_TYPE_BOOL: 731bf215546Sopenharmony_ci /* At this point, we have a scalar, vector, or matrix so we know that 732bf215546Sopenharmony_ci * there cannot be any structure splitting still in the way. By 733bf215546Sopenharmony_ci * stopping at the matrix level rather than the vector level, we 734bf215546Sopenharmony_ci * ensure that matrices get loaded in the optimal way even if they 735bf215546Sopenharmony_ci * are storred row-major in a UBO. 736bf215546Sopenharmony_ci */ 737bf215546Sopenharmony_ci vtn_variable_store(b, vtn_variable_load(b, src, src_access), dest, dest_access); 738bf215546Sopenharmony_ci return; 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci case GLSL_TYPE_INTERFACE: 741bf215546Sopenharmony_ci case GLSL_TYPE_ARRAY: 742bf215546Sopenharmony_ci case GLSL_TYPE_STRUCT: { 743bf215546Sopenharmony_ci struct vtn_access_chain chain = { 744bf215546Sopenharmony_ci .length = 1, 745bf215546Sopenharmony_ci .link = { 746bf215546Sopenharmony_ci { .mode = vtn_access_mode_literal, }, 747bf215546Sopenharmony_ci } 748bf215546Sopenharmony_ci }; 749bf215546Sopenharmony_ci unsigned elems = glsl_get_length(src->type->type); 750bf215546Sopenharmony_ci for (unsigned i = 0; i < elems; i++) { 751bf215546Sopenharmony_ci chain.link[0].id = i; 752bf215546Sopenharmony_ci struct vtn_pointer *src_elem = 753bf215546Sopenharmony_ci vtn_pointer_dereference(b, src, &chain); 754bf215546Sopenharmony_ci struct vtn_pointer *dest_elem = 755bf215546Sopenharmony_ci vtn_pointer_dereference(b, dest, &chain); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci _vtn_variable_copy(b, dest_elem, src_elem, dest_access, src_access); 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci return; 760bf215546Sopenharmony_ci } 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci default: 763bf215546Sopenharmony_ci vtn_fail("Invalid access chain type"); 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci} 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_cistatic void 768bf215546Sopenharmony_civtn_variable_copy(struct vtn_builder *b, struct vtn_pointer *dest, 769bf215546Sopenharmony_ci struct vtn_pointer *src, enum gl_access_qualifier dest_access, 770bf215546Sopenharmony_ci enum gl_access_qualifier src_access) 771bf215546Sopenharmony_ci{ 772bf215546Sopenharmony_ci /* TODO: At some point, we should add a special-case for when we can 773bf215546Sopenharmony_ci * just emit a copy_var intrinsic. 774bf215546Sopenharmony_ci */ 775bf215546Sopenharmony_ci _vtn_variable_copy(b, dest, src, dest_access, src_access); 776bf215546Sopenharmony_ci} 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_cistatic void 779bf215546Sopenharmony_ciset_mode_system_value(struct vtn_builder *b, nir_variable_mode *mode) 780bf215546Sopenharmony_ci{ 781bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_system_value || *mode == nir_var_shader_in || 782bf215546Sopenharmony_ci /* Hack for NV_mesh_shader due to lack of dedicated storage class. */ 783bf215546Sopenharmony_ci *mode == nir_var_mem_task_payload); 784bf215546Sopenharmony_ci *mode = nir_var_system_value; 785bf215546Sopenharmony_ci} 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_cistatic void 788bf215546Sopenharmony_civtn_get_builtin_location(struct vtn_builder *b, 789bf215546Sopenharmony_ci SpvBuiltIn builtin, int *location, 790bf215546Sopenharmony_ci nir_variable_mode *mode) 791bf215546Sopenharmony_ci{ 792bf215546Sopenharmony_ci switch (builtin) { 793bf215546Sopenharmony_ci case SpvBuiltInPosition: 794bf215546Sopenharmony_ci case SpvBuiltInPositionPerViewNV: 795bf215546Sopenharmony_ci *location = VARYING_SLOT_POS; 796bf215546Sopenharmony_ci break; 797bf215546Sopenharmony_ci case SpvBuiltInPointSize: 798bf215546Sopenharmony_ci *location = VARYING_SLOT_PSIZ; 799bf215546Sopenharmony_ci break; 800bf215546Sopenharmony_ci case SpvBuiltInClipDistance: 801bf215546Sopenharmony_ci case SpvBuiltInClipDistancePerViewNV: 802bf215546Sopenharmony_ci *location = VARYING_SLOT_CLIP_DIST0; 803bf215546Sopenharmony_ci break; 804bf215546Sopenharmony_ci case SpvBuiltInCullDistance: 805bf215546Sopenharmony_ci case SpvBuiltInCullDistancePerViewNV: 806bf215546Sopenharmony_ci *location = VARYING_SLOT_CULL_DIST0; 807bf215546Sopenharmony_ci break; 808bf215546Sopenharmony_ci case SpvBuiltInVertexId: 809bf215546Sopenharmony_ci case SpvBuiltInVertexIndex: 810bf215546Sopenharmony_ci /* The Vulkan spec defines VertexIndex to be non-zero-based and doesn't 811bf215546Sopenharmony_ci * allow VertexId. The ARB_gl_spirv spec defines VertexId to be the 812bf215546Sopenharmony_ci * same as gl_VertexID, which is non-zero-based, and removes 813bf215546Sopenharmony_ci * VertexIndex. Since they're both defined to be non-zero-based, we use 814bf215546Sopenharmony_ci * SYSTEM_VALUE_VERTEX_ID for both. 815bf215546Sopenharmony_ci */ 816bf215546Sopenharmony_ci *location = SYSTEM_VALUE_VERTEX_ID; 817bf215546Sopenharmony_ci set_mode_system_value(b, mode); 818bf215546Sopenharmony_ci break; 819bf215546Sopenharmony_ci case SpvBuiltInInstanceIndex: 820bf215546Sopenharmony_ci *location = SYSTEM_VALUE_INSTANCE_INDEX; 821bf215546Sopenharmony_ci set_mode_system_value(b, mode); 822bf215546Sopenharmony_ci break; 823bf215546Sopenharmony_ci case SpvBuiltInInstanceId: 824bf215546Sopenharmony_ci *location = SYSTEM_VALUE_INSTANCE_ID; 825bf215546Sopenharmony_ci set_mode_system_value(b, mode); 826bf215546Sopenharmony_ci break; 827bf215546Sopenharmony_ci case SpvBuiltInPrimitiveId: 828bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_FRAGMENT) { 829bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_in); 830bf215546Sopenharmony_ci *location = VARYING_SLOT_PRIMITIVE_ID; 831bf215546Sopenharmony_ci } else if (*mode == nir_var_shader_out) { 832bf215546Sopenharmony_ci *location = VARYING_SLOT_PRIMITIVE_ID; 833bf215546Sopenharmony_ci } else { 834bf215546Sopenharmony_ci *location = SYSTEM_VALUE_PRIMITIVE_ID; 835bf215546Sopenharmony_ci set_mode_system_value(b, mode); 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci break; 838bf215546Sopenharmony_ci case SpvBuiltInInvocationId: 839bf215546Sopenharmony_ci *location = SYSTEM_VALUE_INVOCATION_ID; 840bf215546Sopenharmony_ci set_mode_system_value(b, mode); 841bf215546Sopenharmony_ci break; 842bf215546Sopenharmony_ci case SpvBuiltInLayer: 843bf215546Sopenharmony_ci case SpvBuiltInLayerPerViewNV: 844bf215546Sopenharmony_ci *location = VARYING_SLOT_LAYER; 845bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_FRAGMENT) 846bf215546Sopenharmony_ci *mode = nir_var_shader_in; 847bf215546Sopenharmony_ci else if (b->shader->info.stage == MESA_SHADER_GEOMETRY) 848bf215546Sopenharmony_ci *mode = nir_var_shader_out; 849bf215546Sopenharmony_ci else if (b->options && b->options->caps.shader_viewport_index_layer && 850bf215546Sopenharmony_ci (b->shader->info.stage == MESA_SHADER_VERTEX || 851bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_TESS_EVAL || 852bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_MESH)) 853bf215546Sopenharmony_ci *mode = nir_var_shader_out; 854bf215546Sopenharmony_ci else 855bf215546Sopenharmony_ci vtn_fail("invalid stage for SpvBuiltInLayer"); 856bf215546Sopenharmony_ci break; 857bf215546Sopenharmony_ci case SpvBuiltInViewportIndex: 858bf215546Sopenharmony_ci *location = VARYING_SLOT_VIEWPORT; 859bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_GEOMETRY) 860bf215546Sopenharmony_ci *mode = nir_var_shader_out; 861bf215546Sopenharmony_ci else if (b->options && b->options->caps.shader_viewport_index_layer && 862bf215546Sopenharmony_ci (b->shader->info.stage == MESA_SHADER_VERTEX || 863bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_TESS_EVAL || 864bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_MESH)) 865bf215546Sopenharmony_ci *mode = nir_var_shader_out; 866bf215546Sopenharmony_ci else if (b->shader->info.stage == MESA_SHADER_FRAGMENT) 867bf215546Sopenharmony_ci *mode = nir_var_shader_in; 868bf215546Sopenharmony_ci else 869bf215546Sopenharmony_ci vtn_fail("invalid stage for SpvBuiltInViewportIndex"); 870bf215546Sopenharmony_ci break; 871bf215546Sopenharmony_ci case SpvBuiltInViewportMaskNV: 872bf215546Sopenharmony_ci case SpvBuiltInViewportMaskPerViewNV: 873bf215546Sopenharmony_ci *location = VARYING_SLOT_VIEWPORT_MASK; 874bf215546Sopenharmony_ci *mode = nir_var_shader_out; 875bf215546Sopenharmony_ci break; 876bf215546Sopenharmony_ci case SpvBuiltInTessLevelOuter: 877bf215546Sopenharmony_ci *location = VARYING_SLOT_TESS_LEVEL_OUTER; 878bf215546Sopenharmony_ci break; 879bf215546Sopenharmony_ci case SpvBuiltInTessLevelInner: 880bf215546Sopenharmony_ci *location = VARYING_SLOT_TESS_LEVEL_INNER; 881bf215546Sopenharmony_ci break; 882bf215546Sopenharmony_ci case SpvBuiltInTessCoord: 883bf215546Sopenharmony_ci *location = SYSTEM_VALUE_TESS_COORD; 884bf215546Sopenharmony_ci set_mode_system_value(b, mode); 885bf215546Sopenharmony_ci break; 886bf215546Sopenharmony_ci case SpvBuiltInPatchVertices: 887bf215546Sopenharmony_ci *location = SYSTEM_VALUE_VERTICES_IN; 888bf215546Sopenharmony_ci set_mode_system_value(b, mode); 889bf215546Sopenharmony_ci break; 890bf215546Sopenharmony_ci case SpvBuiltInFragCoord: 891bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_in); 892bf215546Sopenharmony_ci *mode = nir_var_system_value; 893bf215546Sopenharmony_ci *location = SYSTEM_VALUE_FRAG_COORD; 894bf215546Sopenharmony_ci break; 895bf215546Sopenharmony_ci case SpvBuiltInPointCoord: 896bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_in); 897bf215546Sopenharmony_ci set_mode_system_value(b, mode); 898bf215546Sopenharmony_ci *location = SYSTEM_VALUE_POINT_COORD; 899bf215546Sopenharmony_ci break; 900bf215546Sopenharmony_ci case SpvBuiltInFrontFacing: 901bf215546Sopenharmony_ci *location = SYSTEM_VALUE_FRONT_FACE; 902bf215546Sopenharmony_ci set_mode_system_value(b, mode); 903bf215546Sopenharmony_ci break; 904bf215546Sopenharmony_ci case SpvBuiltInSampleId: 905bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SAMPLE_ID; 906bf215546Sopenharmony_ci set_mode_system_value(b, mode); 907bf215546Sopenharmony_ci break; 908bf215546Sopenharmony_ci case SpvBuiltInSamplePosition: 909bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SAMPLE_POS; 910bf215546Sopenharmony_ci set_mode_system_value(b, mode); 911bf215546Sopenharmony_ci break; 912bf215546Sopenharmony_ci case SpvBuiltInSampleMask: 913bf215546Sopenharmony_ci if (*mode == nir_var_shader_out) { 914bf215546Sopenharmony_ci *location = FRAG_RESULT_SAMPLE_MASK; 915bf215546Sopenharmony_ci } else { 916bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SAMPLE_MASK_IN; 917bf215546Sopenharmony_ci set_mode_system_value(b, mode); 918bf215546Sopenharmony_ci } 919bf215546Sopenharmony_ci break; 920bf215546Sopenharmony_ci case SpvBuiltInFragDepth: 921bf215546Sopenharmony_ci *location = FRAG_RESULT_DEPTH; 922bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_out); 923bf215546Sopenharmony_ci break; 924bf215546Sopenharmony_ci case SpvBuiltInHelperInvocation: 925bf215546Sopenharmony_ci *location = SYSTEM_VALUE_HELPER_INVOCATION; 926bf215546Sopenharmony_ci set_mode_system_value(b, mode); 927bf215546Sopenharmony_ci break; 928bf215546Sopenharmony_ci case SpvBuiltInNumWorkgroups: 929bf215546Sopenharmony_ci *location = SYSTEM_VALUE_NUM_WORKGROUPS; 930bf215546Sopenharmony_ci set_mode_system_value(b, mode); 931bf215546Sopenharmony_ci break; 932bf215546Sopenharmony_ci case SpvBuiltInWorkgroupSize: 933bf215546Sopenharmony_ci case SpvBuiltInEnqueuedWorkgroupSize: 934bf215546Sopenharmony_ci *location = SYSTEM_VALUE_WORKGROUP_SIZE; 935bf215546Sopenharmony_ci set_mode_system_value(b, mode); 936bf215546Sopenharmony_ci break; 937bf215546Sopenharmony_ci case SpvBuiltInWorkgroupId: 938bf215546Sopenharmony_ci *location = SYSTEM_VALUE_WORKGROUP_ID; 939bf215546Sopenharmony_ci set_mode_system_value(b, mode); 940bf215546Sopenharmony_ci break; 941bf215546Sopenharmony_ci case SpvBuiltInLocalInvocationId: 942bf215546Sopenharmony_ci *location = SYSTEM_VALUE_LOCAL_INVOCATION_ID; 943bf215546Sopenharmony_ci set_mode_system_value(b, mode); 944bf215546Sopenharmony_ci break; 945bf215546Sopenharmony_ci case SpvBuiltInLocalInvocationIndex: 946bf215546Sopenharmony_ci *location = SYSTEM_VALUE_LOCAL_INVOCATION_INDEX; 947bf215546Sopenharmony_ci set_mode_system_value(b, mode); 948bf215546Sopenharmony_ci break; 949bf215546Sopenharmony_ci case SpvBuiltInGlobalInvocationId: 950bf215546Sopenharmony_ci *location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID; 951bf215546Sopenharmony_ci set_mode_system_value(b, mode); 952bf215546Sopenharmony_ci break; 953bf215546Sopenharmony_ci case SpvBuiltInGlobalLinearId: 954bf215546Sopenharmony_ci *location = SYSTEM_VALUE_GLOBAL_INVOCATION_INDEX; 955bf215546Sopenharmony_ci set_mode_system_value(b, mode); 956bf215546Sopenharmony_ci break; 957bf215546Sopenharmony_ci case SpvBuiltInGlobalOffset: 958bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BASE_GLOBAL_INVOCATION_ID; 959bf215546Sopenharmony_ci set_mode_system_value(b, mode); 960bf215546Sopenharmony_ci break; 961bf215546Sopenharmony_ci case SpvBuiltInBaseVertex: 962bf215546Sopenharmony_ci /* OpenGL gl_BaseVertex (SYSTEM_VALUE_BASE_VERTEX) is not the same 963bf215546Sopenharmony_ci * semantic as Vulkan BaseVertex (SYSTEM_VALUE_FIRST_VERTEX). 964bf215546Sopenharmony_ci */ 965bf215546Sopenharmony_ci if (b->options->environment == NIR_SPIRV_OPENGL) 966bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BASE_VERTEX; 967bf215546Sopenharmony_ci else 968bf215546Sopenharmony_ci *location = SYSTEM_VALUE_FIRST_VERTEX; 969bf215546Sopenharmony_ci set_mode_system_value(b, mode); 970bf215546Sopenharmony_ci break; 971bf215546Sopenharmony_ci case SpvBuiltInBaseInstance: 972bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BASE_INSTANCE; 973bf215546Sopenharmony_ci set_mode_system_value(b, mode); 974bf215546Sopenharmony_ci break; 975bf215546Sopenharmony_ci case SpvBuiltInDrawIndex: 976bf215546Sopenharmony_ci *location = SYSTEM_VALUE_DRAW_ID; 977bf215546Sopenharmony_ci set_mode_system_value(b, mode); 978bf215546Sopenharmony_ci break; 979bf215546Sopenharmony_ci case SpvBuiltInSubgroupSize: 980bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_SIZE; 981bf215546Sopenharmony_ci set_mode_system_value(b, mode); 982bf215546Sopenharmony_ci break; 983bf215546Sopenharmony_ci case SpvBuiltInSubgroupId: 984bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_ID; 985bf215546Sopenharmony_ci set_mode_system_value(b, mode); 986bf215546Sopenharmony_ci break; 987bf215546Sopenharmony_ci case SpvBuiltInSubgroupLocalInvocationId: 988bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_INVOCATION; 989bf215546Sopenharmony_ci set_mode_system_value(b, mode); 990bf215546Sopenharmony_ci break; 991bf215546Sopenharmony_ci case SpvBuiltInNumSubgroups: 992bf215546Sopenharmony_ci *location = SYSTEM_VALUE_NUM_SUBGROUPS; 993bf215546Sopenharmony_ci set_mode_system_value(b, mode); 994bf215546Sopenharmony_ci break; 995bf215546Sopenharmony_ci case SpvBuiltInDeviceIndex: 996bf215546Sopenharmony_ci *location = SYSTEM_VALUE_DEVICE_INDEX; 997bf215546Sopenharmony_ci set_mode_system_value(b, mode); 998bf215546Sopenharmony_ci break; 999bf215546Sopenharmony_ci case SpvBuiltInViewIndex: 1000bf215546Sopenharmony_ci if (b->options && b->options->view_index_is_input) { 1001bf215546Sopenharmony_ci *location = VARYING_SLOT_VIEW_INDEX; 1002bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_in); 1003bf215546Sopenharmony_ci } else { 1004bf215546Sopenharmony_ci *location = SYSTEM_VALUE_VIEW_INDEX; 1005bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1006bf215546Sopenharmony_ci } 1007bf215546Sopenharmony_ci break; 1008bf215546Sopenharmony_ci case SpvBuiltInSubgroupEqMask: 1009bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_EQ_MASK, 1010bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1011bf215546Sopenharmony_ci break; 1012bf215546Sopenharmony_ci case SpvBuiltInSubgroupGeMask: 1013bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_GE_MASK, 1014bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1015bf215546Sopenharmony_ci break; 1016bf215546Sopenharmony_ci case SpvBuiltInSubgroupGtMask: 1017bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_GT_MASK, 1018bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1019bf215546Sopenharmony_ci break; 1020bf215546Sopenharmony_ci case SpvBuiltInSubgroupLeMask: 1021bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_LE_MASK, 1022bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1023bf215546Sopenharmony_ci break; 1024bf215546Sopenharmony_ci case SpvBuiltInSubgroupLtMask: 1025bf215546Sopenharmony_ci *location = SYSTEM_VALUE_SUBGROUP_LT_MASK, 1026bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1027bf215546Sopenharmony_ci break; 1028bf215546Sopenharmony_ci case SpvBuiltInFragStencilRefEXT: 1029bf215546Sopenharmony_ci *location = FRAG_RESULT_STENCIL; 1030bf215546Sopenharmony_ci vtn_assert(*mode == nir_var_shader_out); 1031bf215546Sopenharmony_ci break; 1032bf215546Sopenharmony_ci case SpvBuiltInWorkDim: 1033bf215546Sopenharmony_ci *location = SYSTEM_VALUE_WORK_DIM; 1034bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1035bf215546Sopenharmony_ci break; 1036bf215546Sopenharmony_ci case SpvBuiltInGlobalSize: 1037bf215546Sopenharmony_ci *location = SYSTEM_VALUE_GLOBAL_GROUP_SIZE; 1038bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1039bf215546Sopenharmony_ci break; 1040bf215546Sopenharmony_ci case SpvBuiltInBaryCoordNoPerspAMD: 1041bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_PIXEL; 1042bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1043bf215546Sopenharmony_ci break; 1044bf215546Sopenharmony_ci case SpvBuiltInBaryCoordNoPerspCentroidAMD: 1045bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID; 1046bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1047bf215546Sopenharmony_ci break; 1048bf215546Sopenharmony_ci case SpvBuiltInBaryCoordNoPerspSampleAMD: 1049bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE; 1050bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1051bf215546Sopenharmony_ci break; 1052bf215546Sopenharmony_ci case SpvBuiltInBaryCoordSmoothAMD: 1053bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_PIXEL; 1054bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1055bf215546Sopenharmony_ci break; 1056bf215546Sopenharmony_ci case SpvBuiltInBaryCoordSmoothCentroidAMD: 1057bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID; 1058bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1059bf215546Sopenharmony_ci break; 1060bf215546Sopenharmony_ci case SpvBuiltInBaryCoordSmoothSampleAMD: 1061bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE; 1062bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1063bf215546Sopenharmony_ci break; 1064bf215546Sopenharmony_ci case SpvBuiltInBaryCoordPullModelAMD: 1065bf215546Sopenharmony_ci *location = SYSTEM_VALUE_BARYCENTRIC_PULL_MODEL; 1066bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1067bf215546Sopenharmony_ci break; 1068bf215546Sopenharmony_ci case SpvBuiltInLaunchIdKHR: 1069bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_LAUNCH_ID; 1070bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1071bf215546Sopenharmony_ci break; 1072bf215546Sopenharmony_ci case SpvBuiltInLaunchSizeKHR: 1073bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_LAUNCH_SIZE; 1074bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1075bf215546Sopenharmony_ci break; 1076bf215546Sopenharmony_ci case SpvBuiltInWorldRayOriginKHR: 1077bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_WORLD_ORIGIN; 1078bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1079bf215546Sopenharmony_ci break; 1080bf215546Sopenharmony_ci case SpvBuiltInWorldRayDirectionKHR: 1081bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_WORLD_DIRECTION; 1082bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1083bf215546Sopenharmony_ci break; 1084bf215546Sopenharmony_ci case SpvBuiltInObjectRayOriginKHR: 1085bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_OBJECT_ORIGIN; 1086bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1087bf215546Sopenharmony_ci break; 1088bf215546Sopenharmony_ci case SpvBuiltInObjectRayDirectionKHR: 1089bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_OBJECT_DIRECTION; 1090bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1091bf215546Sopenharmony_ci break; 1092bf215546Sopenharmony_ci case SpvBuiltInObjectToWorldKHR: 1093bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_OBJECT_TO_WORLD; 1094bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1095bf215546Sopenharmony_ci break; 1096bf215546Sopenharmony_ci case SpvBuiltInWorldToObjectKHR: 1097bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_WORLD_TO_OBJECT; 1098bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1099bf215546Sopenharmony_ci break; 1100bf215546Sopenharmony_ci case SpvBuiltInRayTminKHR: 1101bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_T_MIN; 1102bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1103bf215546Sopenharmony_ci break; 1104bf215546Sopenharmony_ci case SpvBuiltInRayTmaxKHR: 1105bf215546Sopenharmony_ci case SpvBuiltInHitTNV: 1106bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_T_MAX; 1107bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1108bf215546Sopenharmony_ci break; 1109bf215546Sopenharmony_ci case SpvBuiltInInstanceCustomIndexKHR: 1110bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_INSTANCE_CUSTOM_INDEX; 1111bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1112bf215546Sopenharmony_ci break; 1113bf215546Sopenharmony_ci case SpvBuiltInHitKindKHR: 1114bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_HIT_KIND; 1115bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1116bf215546Sopenharmony_ci break; 1117bf215546Sopenharmony_ci case SpvBuiltInIncomingRayFlagsKHR: 1118bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_FLAGS; 1119bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1120bf215546Sopenharmony_ci break; 1121bf215546Sopenharmony_ci case SpvBuiltInRayGeometryIndexKHR: 1122bf215546Sopenharmony_ci *location = SYSTEM_VALUE_RAY_GEOMETRY_INDEX; 1123bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1124bf215546Sopenharmony_ci break; 1125bf215546Sopenharmony_ci case SpvBuiltInCullMaskKHR: 1126bf215546Sopenharmony_ci *location = SYSTEM_VALUE_CULL_MASK; 1127bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1128bf215546Sopenharmony_ci break; 1129bf215546Sopenharmony_ci case SpvBuiltInShadingRateKHR: 1130bf215546Sopenharmony_ci *location = SYSTEM_VALUE_FRAG_SHADING_RATE; 1131bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1132bf215546Sopenharmony_ci break; 1133bf215546Sopenharmony_ci case SpvBuiltInPrimitiveShadingRateKHR: 1134bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_VERTEX || 1135bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_GEOMETRY || 1136bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_MESH) { 1137bf215546Sopenharmony_ci *location = VARYING_SLOT_PRIMITIVE_SHADING_RATE; 1138bf215546Sopenharmony_ci *mode = nir_var_shader_out; 1139bf215546Sopenharmony_ci } else { 1140bf215546Sopenharmony_ci vtn_fail("invalid stage for SpvBuiltInPrimitiveShadingRateKHR"); 1141bf215546Sopenharmony_ci } 1142bf215546Sopenharmony_ci break; 1143bf215546Sopenharmony_ci case SpvBuiltInPrimitiveCountNV: 1144bf215546Sopenharmony_ci *location = VARYING_SLOT_PRIMITIVE_COUNT; 1145bf215546Sopenharmony_ci break; 1146bf215546Sopenharmony_ci case SpvBuiltInPrimitiveIndicesNV: 1147bf215546Sopenharmony_ci *location = VARYING_SLOT_PRIMITIVE_INDICES; 1148bf215546Sopenharmony_ci break; 1149bf215546Sopenharmony_ci case SpvBuiltInTaskCountNV: 1150bf215546Sopenharmony_ci /* NV_mesh_shader only. */ 1151bf215546Sopenharmony_ci *location = VARYING_SLOT_TASK_COUNT; 1152bf215546Sopenharmony_ci *mode = nir_var_shader_out; 1153bf215546Sopenharmony_ci break; 1154bf215546Sopenharmony_ci case SpvBuiltInMeshViewCountNV: 1155bf215546Sopenharmony_ci *location = SYSTEM_VALUE_MESH_VIEW_COUNT; 1156bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1157bf215546Sopenharmony_ci break; 1158bf215546Sopenharmony_ci case SpvBuiltInMeshViewIndicesNV: 1159bf215546Sopenharmony_ci *location = SYSTEM_VALUE_MESH_VIEW_INDICES; 1160bf215546Sopenharmony_ci set_mode_system_value(b, mode); 1161bf215546Sopenharmony_ci break; 1162bf215546Sopenharmony_ci default: 1163bf215546Sopenharmony_ci vtn_fail("Unsupported builtin: %s (%u)", 1164bf215546Sopenharmony_ci spirv_builtin_to_string(builtin), builtin); 1165bf215546Sopenharmony_ci } 1166bf215546Sopenharmony_ci} 1167bf215546Sopenharmony_ci 1168bf215546Sopenharmony_cistatic void 1169bf215546Sopenharmony_ciapply_var_decoration(struct vtn_builder *b, 1170bf215546Sopenharmony_ci struct nir_variable_data *var_data, 1171bf215546Sopenharmony_ci const struct vtn_decoration *dec) 1172bf215546Sopenharmony_ci{ 1173bf215546Sopenharmony_ci switch (dec->decoration) { 1174bf215546Sopenharmony_ci case SpvDecorationRelaxedPrecision: 1175bf215546Sopenharmony_ci var_data->precision = GLSL_PRECISION_MEDIUM; 1176bf215546Sopenharmony_ci break; 1177bf215546Sopenharmony_ci case SpvDecorationNoPerspective: 1178bf215546Sopenharmony_ci var_data->interpolation = INTERP_MODE_NOPERSPECTIVE; 1179bf215546Sopenharmony_ci break; 1180bf215546Sopenharmony_ci case SpvDecorationFlat: 1181bf215546Sopenharmony_ci var_data->interpolation = INTERP_MODE_FLAT; 1182bf215546Sopenharmony_ci break; 1183bf215546Sopenharmony_ci case SpvDecorationExplicitInterpAMD: 1184bf215546Sopenharmony_ci var_data->interpolation = INTERP_MODE_EXPLICIT; 1185bf215546Sopenharmony_ci break; 1186bf215546Sopenharmony_ci case SpvDecorationCentroid: 1187bf215546Sopenharmony_ci var_data->centroid = true; 1188bf215546Sopenharmony_ci break; 1189bf215546Sopenharmony_ci case SpvDecorationSample: 1190bf215546Sopenharmony_ci var_data->sample = true; 1191bf215546Sopenharmony_ci break; 1192bf215546Sopenharmony_ci case SpvDecorationInvariant: 1193bf215546Sopenharmony_ci var_data->invariant = true; 1194bf215546Sopenharmony_ci break; 1195bf215546Sopenharmony_ci case SpvDecorationConstant: 1196bf215546Sopenharmony_ci var_data->read_only = true; 1197bf215546Sopenharmony_ci break; 1198bf215546Sopenharmony_ci case SpvDecorationNonReadable: 1199bf215546Sopenharmony_ci var_data->access |= ACCESS_NON_READABLE; 1200bf215546Sopenharmony_ci break; 1201bf215546Sopenharmony_ci case SpvDecorationNonWritable: 1202bf215546Sopenharmony_ci var_data->read_only = true; 1203bf215546Sopenharmony_ci var_data->access |= ACCESS_NON_WRITEABLE; 1204bf215546Sopenharmony_ci break; 1205bf215546Sopenharmony_ci case SpvDecorationRestrict: 1206bf215546Sopenharmony_ci var_data->access |= ACCESS_RESTRICT; 1207bf215546Sopenharmony_ci break; 1208bf215546Sopenharmony_ci case SpvDecorationAliased: 1209bf215546Sopenharmony_ci var_data->access &= ~ACCESS_RESTRICT; 1210bf215546Sopenharmony_ci break; 1211bf215546Sopenharmony_ci case SpvDecorationVolatile: 1212bf215546Sopenharmony_ci var_data->access |= ACCESS_VOLATILE; 1213bf215546Sopenharmony_ci break; 1214bf215546Sopenharmony_ci case SpvDecorationCoherent: 1215bf215546Sopenharmony_ci var_data->access |= ACCESS_COHERENT; 1216bf215546Sopenharmony_ci break; 1217bf215546Sopenharmony_ci case SpvDecorationComponent: 1218bf215546Sopenharmony_ci var_data->location_frac = dec->operands[0]; 1219bf215546Sopenharmony_ci break; 1220bf215546Sopenharmony_ci case SpvDecorationIndex: 1221bf215546Sopenharmony_ci var_data->index = dec->operands[0]; 1222bf215546Sopenharmony_ci break; 1223bf215546Sopenharmony_ci case SpvDecorationBuiltIn: { 1224bf215546Sopenharmony_ci SpvBuiltIn builtin = dec->operands[0]; 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci nir_variable_mode mode = var_data->mode; 1227bf215546Sopenharmony_ci vtn_get_builtin_location(b, builtin, &var_data->location, &mode); 1228bf215546Sopenharmony_ci var_data->mode = mode; 1229bf215546Sopenharmony_ci 1230bf215546Sopenharmony_ci switch (builtin) { 1231bf215546Sopenharmony_ci case SpvBuiltInTessLevelOuter: 1232bf215546Sopenharmony_ci case SpvBuiltInTessLevelInner: 1233bf215546Sopenharmony_ci case SpvBuiltInClipDistance: 1234bf215546Sopenharmony_ci case SpvBuiltInClipDistancePerViewNV: 1235bf215546Sopenharmony_ci case SpvBuiltInCullDistance: 1236bf215546Sopenharmony_ci case SpvBuiltInCullDistancePerViewNV: 1237bf215546Sopenharmony_ci var_data->compact = true; 1238bf215546Sopenharmony_ci break; 1239bf215546Sopenharmony_ci default: 1240bf215546Sopenharmony_ci break; 1241bf215546Sopenharmony_ci } 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci break; 1244bf215546Sopenharmony_ci } 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci case SpvDecorationSpecId: 1247bf215546Sopenharmony_ci case SpvDecorationRowMajor: 1248bf215546Sopenharmony_ci case SpvDecorationColMajor: 1249bf215546Sopenharmony_ci case SpvDecorationMatrixStride: 1250bf215546Sopenharmony_ci case SpvDecorationUniform: 1251bf215546Sopenharmony_ci case SpvDecorationUniformId: 1252bf215546Sopenharmony_ci case SpvDecorationLinkageAttributes: 1253bf215546Sopenharmony_ci break; /* Do nothing with these here */ 1254bf215546Sopenharmony_ci 1255bf215546Sopenharmony_ci case SpvDecorationPatch: 1256bf215546Sopenharmony_ci var_data->patch = true; 1257bf215546Sopenharmony_ci break; 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci case SpvDecorationLocation: 1260bf215546Sopenharmony_ci vtn_fail("Should be handled earlier by var_decoration_cb()"); 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci case SpvDecorationBlock: 1263bf215546Sopenharmony_ci case SpvDecorationBufferBlock: 1264bf215546Sopenharmony_ci case SpvDecorationArrayStride: 1265bf215546Sopenharmony_ci case SpvDecorationGLSLShared: 1266bf215546Sopenharmony_ci case SpvDecorationGLSLPacked: 1267bf215546Sopenharmony_ci break; /* These can apply to a type but we don't care about them */ 1268bf215546Sopenharmony_ci 1269bf215546Sopenharmony_ci case SpvDecorationBinding: 1270bf215546Sopenharmony_ci case SpvDecorationDescriptorSet: 1271bf215546Sopenharmony_ci case SpvDecorationNoContraction: 1272bf215546Sopenharmony_ci case SpvDecorationInputAttachmentIndex: 1273bf215546Sopenharmony_ci vtn_warn("Decoration not allowed for variable or structure member: %s", 1274bf215546Sopenharmony_ci spirv_decoration_to_string(dec->decoration)); 1275bf215546Sopenharmony_ci break; 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci case SpvDecorationXfbBuffer: 1278bf215546Sopenharmony_ci var_data->explicit_xfb_buffer = true; 1279bf215546Sopenharmony_ci var_data->xfb.buffer = dec->operands[0]; 1280bf215546Sopenharmony_ci var_data->always_active_io = true; 1281bf215546Sopenharmony_ci break; 1282bf215546Sopenharmony_ci case SpvDecorationXfbStride: 1283bf215546Sopenharmony_ci var_data->explicit_xfb_stride = true; 1284bf215546Sopenharmony_ci var_data->xfb.stride = dec->operands[0]; 1285bf215546Sopenharmony_ci break; 1286bf215546Sopenharmony_ci case SpvDecorationOffset: 1287bf215546Sopenharmony_ci var_data->explicit_offset = true; 1288bf215546Sopenharmony_ci var_data->offset = dec->operands[0]; 1289bf215546Sopenharmony_ci break; 1290bf215546Sopenharmony_ci 1291bf215546Sopenharmony_ci case SpvDecorationStream: 1292bf215546Sopenharmony_ci var_data->stream = dec->operands[0]; 1293bf215546Sopenharmony_ci break; 1294bf215546Sopenharmony_ci 1295bf215546Sopenharmony_ci case SpvDecorationCPacked: 1296bf215546Sopenharmony_ci case SpvDecorationSaturatedConversion: 1297bf215546Sopenharmony_ci case SpvDecorationFuncParamAttr: 1298bf215546Sopenharmony_ci case SpvDecorationFPRoundingMode: 1299bf215546Sopenharmony_ci case SpvDecorationFPFastMathMode: 1300bf215546Sopenharmony_ci case SpvDecorationAlignment: 1301bf215546Sopenharmony_ci if (b->shader->info.stage != MESA_SHADER_KERNEL) { 1302bf215546Sopenharmony_ci vtn_warn("Decoration only allowed for CL-style kernels: %s", 1303bf215546Sopenharmony_ci spirv_decoration_to_string(dec->decoration)); 1304bf215546Sopenharmony_ci } 1305bf215546Sopenharmony_ci break; 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci case SpvDecorationUserSemantic: 1308bf215546Sopenharmony_ci case SpvDecorationUserTypeGOOGLE: 1309bf215546Sopenharmony_ci /* User semantic decorations can safely be ignored by the driver. */ 1310bf215546Sopenharmony_ci break; 1311bf215546Sopenharmony_ci 1312bf215546Sopenharmony_ci case SpvDecorationRestrictPointerEXT: 1313bf215546Sopenharmony_ci case SpvDecorationAliasedPointerEXT: 1314bf215546Sopenharmony_ci /* TODO: We should actually plumb alias information through NIR. */ 1315bf215546Sopenharmony_ci break; 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci case SpvDecorationPerPrimitiveNV: 1318bf215546Sopenharmony_ci vtn_fail_if( 1319bf215546Sopenharmony_ci !(b->shader->info.stage == MESA_SHADER_MESH && var_data->mode == nir_var_shader_out) && 1320bf215546Sopenharmony_ci !(b->shader->info.stage == MESA_SHADER_FRAGMENT && var_data->mode == nir_var_shader_in), 1321bf215546Sopenharmony_ci "PerPrimitiveNV decoration only allowed for Mesh shader outputs or Fragment shader inputs"); 1322bf215546Sopenharmony_ci var_data->per_primitive = true; 1323bf215546Sopenharmony_ci break; 1324bf215546Sopenharmony_ci 1325bf215546Sopenharmony_ci case SpvDecorationPerTaskNV: 1326bf215546Sopenharmony_ci vtn_fail_if( 1327bf215546Sopenharmony_ci (b->shader->info.stage != MESA_SHADER_MESH && 1328bf215546Sopenharmony_ci b->shader->info.stage != MESA_SHADER_TASK) || 1329bf215546Sopenharmony_ci var_data->mode != nir_var_mem_task_payload, 1330bf215546Sopenharmony_ci "PerTaskNV decoration only allowed on Task/Mesh payload variables."); 1331bf215546Sopenharmony_ci break; 1332bf215546Sopenharmony_ci 1333bf215546Sopenharmony_ci case SpvDecorationPerViewNV: 1334bf215546Sopenharmony_ci vtn_fail_if(b->shader->info.stage != MESA_SHADER_MESH, 1335bf215546Sopenharmony_ci "PerViewNV decoration only allowed in Mesh shaders"); 1336bf215546Sopenharmony_ci var_data->per_view = true; 1337bf215546Sopenharmony_ci break; 1338bf215546Sopenharmony_ci 1339bf215546Sopenharmony_ci default: 1340bf215546Sopenharmony_ci vtn_fail_with_decoration("Unhandled decoration", dec->decoration); 1341bf215546Sopenharmony_ci } 1342bf215546Sopenharmony_ci} 1343bf215546Sopenharmony_ci 1344bf215546Sopenharmony_cistatic void 1345bf215546Sopenharmony_cigather_var_kind_cb(struct vtn_builder *b, struct vtn_value *val, int member, 1346bf215546Sopenharmony_ci const struct vtn_decoration *dec, void *void_var) 1347bf215546Sopenharmony_ci{ 1348bf215546Sopenharmony_ci struct vtn_variable *vtn_var = void_var; 1349bf215546Sopenharmony_ci switch (dec->decoration) { 1350bf215546Sopenharmony_ci case SpvDecorationPatch: 1351bf215546Sopenharmony_ci vtn_var->var->data.patch = true; 1352bf215546Sopenharmony_ci break; 1353bf215546Sopenharmony_ci case SpvDecorationPerPrimitiveNV: 1354bf215546Sopenharmony_ci vtn_var->var->data.per_primitive = true; 1355bf215546Sopenharmony_ci break; 1356bf215546Sopenharmony_ci case SpvDecorationPerViewNV: 1357bf215546Sopenharmony_ci vtn_var->var->data.per_view = true; 1358bf215546Sopenharmony_ci break; 1359bf215546Sopenharmony_ci default: 1360bf215546Sopenharmony_ci /* Nothing to do. */ 1361bf215546Sopenharmony_ci break; 1362bf215546Sopenharmony_ci } 1363bf215546Sopenharmony_ci} 1364bf215546Sopenharmony_ci 1365bf215546Sopenharmony_cistatic void 1366bf215546Sopenharmony_civar_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, 1367bf215546Sopenharmony_ci const struct vtn_decoration *dec, void *void_var) 1368bf215546Sopenharmony_ci{ 1369bf215546Sopenharmony_ci struct vtn_variable *vtn_var = void_var; 1370bf215546Sopenharmony_ci 1371bf215546Sopenharmony_ci /* Handle decorations that apply to a vtn_variable as a whole */ 1372bf215546Sopenharmony_ci switch (dec->decoration) { 1373bf215546Sopenharmony_ci case SpvDecorationBinding: 1374bf215546Sopenharmony_ci vtn_var->binding = dec->operands[0]; 1375bf215546Sopenharmony_ci vtn_var->explicit_binding = true; 1376bf215546Sopenharmony_ci return; 1377bf215546Sopenharmony_ci case SpvDecorationDescriptorSet: 1378bf215546Sopenharmony_ci vtn_var->descriptor_set = dec->operands[0]; 1379bf215546Sopenharmony_ci return; 1380bf215546Sopenharmony_ci case SpvDecorationInputAttachmentIndex: 1381bf215546Sopenharmony_ci vtn_var->input_attachment_index = dec->operands[0]; 1382bf215546Sopenharmony_ci return; 1383bf215546Sopenharmony_ci case SpvDecorationPatch: 1384bf215546Sopenharmony_ci vtn_var->var->data.patch = true; 1385bf215546Sopenharmony_ci break; 1386bf215546Sopenharmony_ci case SpvDecorationOffset: 1387bf215546Sopenharmony_ci vtn_var->offset = dec->operands[0]; 1388bf215546Sopenharmony_ci break; 1389bf215546Sopenharmony_ci case SpvDecorationNonWritable: 1390bf215546Sopenharmony_ci vtn_var->access |= ACCESS_NON_WRITEABLE; 1391bf215546Sopenharmony_ci break; 1392bf215546Sopenharmony_ci case SpvDecorationNonReadable: 1393bf215546Sopenharmony_ci vtn_var->access |= ACCESS_NON_READABLE; 1394bf215546Sopenharmony_ci break; 1395bf215546Sopenharmony_ci case SpvDecorationVolatile: 1396bf215546Sopenharmony_ci vtn_var->access |= ACCESS_VOLATILE; 1397bf215546Sopenharmony_ci break; 1398bf215546Sopenharmony_ci case SpvDecorationCoherent: 1399bf215546Sopenharmony_ci vtn_var->access |= ACCESS_COHERENT; 1400bf215546Sopenharmony_ci break; 1401bf215546Sopenharmony_ci case SpvDecorationCounterBuffer: 1402bf215546Sopenharmony_ci /* Counter buffer decorations can safely be ignored by the driver. */ 1403bf215546Sopenharmony_ci return; 1404bf215546Sopenharmony_ci default: 1405bf215546Sopenharmony_ci break; 1406bf215546Sopenharmony_ci } 1407bf215546Sopenharmony_ci 1408bf215546Sopenharmony_ci if (val->value_type == vtn_value_type_pointer) { 1409bf215546Sopenharmony_ci assert(val->pointer->var == void_var); 1410bf215546Sopenharmony_ci assert(member == -1); 1411bf215546Sopenharmony_ci } else { 1412bf215546Sopenharmony_ci assert(val->value_type == vtn_value_type_type); 1413bf215546Sopenharmony_ci } 1414bf215546Sopenharmony_ci 1415bf215546Sopenharmony_ci /* Location is odd. If applied to a split structure, we have to walk the 1416bf215546Sopenharmony_ci * whole thing and accumulate the location. It's easier to handle as a 1417bf215546Sopenharmony_ci * special case. 1418bf215546Sopenharmony_ci */ 1419bf215546Sopenharmony_ci if (dec->decoration == SpvDecorationLocation) { 1420bf215546Sopenharmony_ci unsigned location = dec->operands[0]; 1421bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_FRAGMENT && 1422bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_output) { 1423bf215546Sopenharmony_ci location += FRAG_RESULT_DATA0; 1424bf215546Sopenharmony_ci } else if (b->shader->info.stage == MESA_SHADER_VERTEX && 1425bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_input) { 1426bf215546Sopenharmony_ci location += VERT_ATTRIB_GENERIC0; 1427bf215546Sopenharmony_ci } else if (vtn_var->mode == vtn_variable_mode_input || 1428bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_output) { 1429bf215546Sopenharmony_ci location += vtn_var->var->data.patch ? VARYING_SLOT_PATCH0 : VARYING_SLOT_VAR0; 1430bf215546Sopenharmony_ci } else if (vtn_var->mode == vtn_variable_mode_call_data || 1431bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_ray_payload) { 1432bf215546Sopenharmony_ci /* This location is fine as-is */ 1433bf215546Sopenharmony_ci } else if (vtn_var->mode != vtn_variable_mode_uniform && 1434bf215546Sopenharmony_ci vtn_var->mode != vtn_variable_mode_image) { 1435bf215546Sopenharmony_ci vtn_warn("Location must be on input, output, uniform, sampler or " 1436bf215546Sopenharmony_ci "image variable"); 1437bf215546Sopenharmony_ci return; 1438bf215546Sopenharmony_ci } 1439bf215546Sopenharmony_ci 1440bf215546Sopenharmony_ci if (vtn_var->var->num_members == 0) { 1441bf215546Sopenharmony_ci /* This handles the member and lone variable cases */ 1442bf215546Sopenharmony_ci vtn_var->var->data.location = location; 1443bf215546Sopenharmony_ci } else { 1444bf215546Sopenharmony_ci /* This handles the structure member case */ 1445bf215546Sopenharmony_ci assert(vtn_var->var->members); 1446bf215546Sopenharmony_ci 1447bf215546Sopenharmony_ci if (member == -1) 1448bf215546Sopenharmony_ci vtn_var->base_location = location; 1449bf215546Sopenharmony_ci else 1450bf215546Sopenharmony_ci vtn_var->var->members[member].location = location; 1451bf215546Sopenharmony_ci } 1452bf215546Sopenharmony_ci 1453bf215546Sopenharmony_ci return; 1454bf215546Sopenharmony_ci } else { 1455bf215546Sopenharmony_ci if (vtn_var->var) { 1456bf215546Sopenharmony_ci if (vtn_var->var->num_members == 0) { 1457bf215546Sopenharmony_ci /* We call this function on types as well as variables and not all 1458bf215546Sopenharmony_ci * struct types get split so we can end up having stray member 1459bf215546Sopenharmony_ci * decorations; just ignore them. 1460bf215546Sopenharmony_ci */ 1461bf215546Sopenharmony_ci if (member == -1) 1462bf215546Sopenharmony_ci apply_var_decoration(b, &vtn_var->var->data, dec); 1463bf215546Sopenharmony_ci } else if (member >= 0) { 1464bf215546Sopenharmony_ci /* Member decorations must come from a type */ 1465bf215546Sopenharmony_ci assert(val->value_type == vtn_value_type_type); 1466bf215546Sopenharmony_ci apply_var_decoration(b, &vtn_var->var->members[member], dec); 1467bf215546Sopenharmony_ci } else { 1468bf215546Sopenharmony_ci unsigned length = 1469bf215546Sopenharmony_ci glsl_get_length(glsl_without_array(vtn_var->type->type)); 1470bf215546Sopenharmony_ci for (unsigned i = 0; i < length; i++) 1471bf215546Sopenharmony_ci apply_var_decoration(b, &vtn_var->var->members[i], dec); 1472bf215546Sopenharmony_ci } 1473bf215546Sopenharmony_ci } else { 1474bf215546Sopenharmony_ci /* A few variables, those with external storage, have no actual 1475bf215546Sopenharmony_ci * nir_variables associated with them. Fortunately, all decorations 1476bf215546Sopenharmony_ci * we care about for those variables are on the type only. 1477bf215546Sopenharmony_ci */ 1478bf215546Sopenharmony_ci vtn_assert(vtn_var->mode == vtn_variable_mode_ubo || 1479bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_ssbo || 1480bf215546Sopenharmony_ci vtn_var->mode == vtn_variable_mode_push_constant); 1481bf215546Sopenharmony_ci } 1482bf215546Sopenharmony_ci } 1483bf215546Sopenharmony_ci} 1484bf215546Sopenharmony_ci 1485bf215546Sopenharmony_cienum vtn_variable_mode 1486bf215546Sopenharmony_civtn_storage_class_to_mode(struct vtn_builder *b, 1487bf215546Sopenharmony_ci SpvStorageClass class, 1488bf215546Sopenharmony_ci struct vtn_type *interface_type, 1489bf215546Sopenharmony_ci nir_variable_mode *nir_mode_out) 1490bf215546Sopenharmony_ci{ 1491bf215546Sopenharmony_ci enum vtn_variable_mode mode; 1492bf215546Sopenharmony_ci nir_variable_mode nir_mode; 1493bf215546Sopenharmony_ci switch (class) { 1494bf215546Sopenharmony_ci case SpvStorageClassUniform: 1495bf215546Sopenharmony_ci /* Assume it's an UBO if we lack the interface_type. */ 1496bf215546Sopenharmony_ci if (!interface_type || interface_type->block) { 1497bf215546Sopenharmony_ci mode = vtn_variable_mode_ubo; 1498bf215546Sopenharmony_ci nir_mode = nir_var_mem_ubo; 1499bf215546Sopenharmony_ci } else if (interface_type->buffer_block) { 1500bf215546Sopenharmony_ci mode = vtn_variable_mode_ssbo; 1501bf215546Sopenharmony_ci nir_mode = nir_var_mem_ssbo; 1502bf215546Sopenharmony_ci } else { 1503bf215546Sopenharmony_ci /* Default-block uniforms, coming from gl_spirv */ 1504bf215546Sopenharmony_ci mode = vtn_variable_mode_uniform; 1505bf215546Sopenharmony_ci nir_mode = nir_var_uniform; 1506bf215546Sopenharmony_ci } 1507bf215546Sopenharmony_ci break; 1508bf215546Sopenharmony_ci case SpvStorageClassStorageBuffer: 1509bf215546Sopenharmony_ci mode = vtn_variable_mode_ssbo; 1510bf215546Sopenharmony_ci nir_mode = nir_var_mem_ssbo; 1511bf215546Sopenharmony_ci break; 1512bf215546Sopenharmony_ci case SpvStorageClassPhysicalStorageBuffer: 1513bf215546Sopenharmony_ci mode = vtn_variable_mode_phys_ssbo; 1514bf215546Sopenharmony_ci nir_mode = nir_var_mem_global; 1515bf215546Sopenharmony_ci break; 1516bf215546Sopenharmony_ci case SpvStorageClassUniformConstant: 1517bf215546Sopenharmony_ci /* interface_type is only NULL when OpTypeForwardPointer is used and 1518bf215546Sopenharmony_ci * OpTypeForwardPointer can only be used for struct types, not images or 1519bf215546Sopenharmony_ci * acceleration structures. 1520bf215546Sopenharmony_ci */ 1521bf215546Sopenharmony_ci if (interface_type) 1522bf215546Sopenharmony_ci interface_type = vtn_type_without_array(interface_type); 1523bf215546Sopenharmony_ci 1524bf215546Sopenharmony_ci if (interface_type && 1525bf215546Sopenharmony_ci interface_type->base_type == vtn_base_type_image && 1526bf215546Sopenharmony_ci glsl_type_is_image(interface_type->glsl_image)) { 1527bf215546Sopenharmony_ci mode = vtn_variable_mode_image; 1528bf215546Sopenharmony_ci nir_mode = nir_var_image; 1529bf215546Sopenharmony_ci } else if (b->shader->info.stage == MESA_SHADER_KERNEL) { 1530bf215546Sopenharmony_ci mode = vtn_variable_mode_constant; 1531bf215546Sopenharmony_ci nir_mode = nir_var_mem_constant; 1532bf215546Sopenharmony_ci } else { 1533bf215546Sopenharmony_ci /* interface_type is only NULL when OpTypeForwardPointer is used and 1534bf215546Sopenharmony_ci * OpTypeForwardPointer cannot be used with the UniformConstant 1535bf215546Sopenharmony_ci * storage class. 1536bf215546Sopenharmony_ci */ 1537bf215546Sopenharmony_ci assert(interface_type != NULL); 1538bf215546Sopenharmony_ci if (interface_type->base_type == vtn_base_type_accel_struct) { 1539bf215546Sopenharmony_ci mode = vtn_variable_mode_accel_struct; 1540bf215546Sopenharmony_ci nir_mode = nir_var_uniform; 1541bf215546Sopenharmony_ci } else { 1542bf215546Sopenharmony_ci mode = vtn_variable_mode_uniform; 1543bf215546Sopenharmony_ci nir_mode = nir_var_uniform; 1544bf215546Sopenharmony_ci } 1545bf215546Sopenharmony_ci } 1546bf215546Sopenharmony_ci break; 1547bf215546Sopenharmony_ci case SpvStorageClassPushConstant: 1548bf215546Sopenharmony_ci mode = vtn_variable_mode_push_constant; 1549bf215546Sopenharmony_ci nir_mode = nir_var_mem_push_const; 1550bf215546Sopenharmony_ci break; 1551bf215546Sopenharmony_ci case SpvStorageClassInput: 1552bf215546Sopenharmony_ci mode = vtn_variable_mode_input; 1553bf215546Sopenharmony_ci nir_mode = nir_var_shader_in; 1554bf215546Sopenharmony_ci 1555bf215546Sopenharmony_ci /* NV_mesh_shader: fixup due to lack of dedicated storage class */ 1556bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_MESH) { 1557bf215546Sopenharmony_ci mode = vtn_variable_mode_task_payload; 1558bf215546Sopenharmony_ci nir_mode = nir_var_mem_task_payload; 1559bf215546Sopenharmony_ci } 1560bf215546Sopenharmony_ci break; 1561bf215546Sopenharmony_ci case SpvStorageClassOutput: 1562bf215546Sopenharmony_ci mode = vtn_variable_mode_output; 1563bf215546Sopenharmony_ci nir_mode = nir_var_shader_out; 1564bf215546Sopenharmony_ci 1565bf215546Sopenharmony_ci /* NV_mesh_shader: fixup due to lack of dedicated storage class */ 1566bf215546Sopenharmony_ci if (b->shader->info.stage == MESA_SHADER_TASK) { 1567bf215546Sopenharmony_ci mode = vtn_variable_mode_task_payload; 1568bf215546Sopenharmony_ci nir_mode = nir_var_mem_task_payload; 1569bf215546Sopenharmony_ci } 1570bf215546Sopenharmony_ci break; 1571bf215546Sopenharmony_ci case SpvStorageClassPrivate: 1572bf215546Sopenharmony_ci mode = vtn_variable_mode_private; 1573bf215546Sopenharmony_ci nir_mode = nir_var_shader_temp; 1574bf215546Sopenharmony_ci break; 1575bf215546Sopenharmony_ci case SpvStorageClassFunction: 1576bf215546Sopenharmony_ci mode = vtn_variable_mode_function; 1577bf215546Sopenharmony_ci nir_mode = nir_var_function_temp; 1578bf215546Sopenharmony_ci break; 1579bf215546Sopenharmony_ci case SpvStorageClassWorkgroup: 1580bf215546Sopenharmony_ci mode = vtn_variable_mode_workgroup; 1581bf215546Sopenharmony_ci nir_mode = nir_var_mem_shared; 1582bf215546Sopenharmony_ci break; 1583bf215546Sopenharmony_ci case SpvStorageClassAtomicCounter: 1584bf215546Sopenharmony_ci mode = vtn_variable_mode_atomic_counter; 1585bf215546Sopenharmony_ci nir_mode = nir_var_uniform; 1586bf215546Sopenharmony_ci break; 1587bf215546Sopenharmony_ci case SpvStorageClassCrossWorkgroup: 1588bf215546Sopenharmony_ci mode = vtn_variable_mode_cross_workgroup; 1589bf215546Sopenharmony_ci nir_mode = nir_var_mem_global; 1590bf215546Sopenharmony_ci break; 1591bf215546Sopenharmony_ci case SpvStorageClassImage: 1592bf215546Sopenharmony_ci mode = vtn_variable_mode_image; 1593bf215546Sopenharmony_ci nir_mode = nir_var_image; 1594bf215546Sopenharmony_ci break; 1595bf215546Sopenharmony_ci case SpvStorageClassCallableDataKHR: 1596bf215546Sopenharmony_ci mode = vtn_variable_mode_call_data; 1597bf215546Sopenharmony_ci nir_mode = nir_var_shader_temp; 1598bf215546Sopenharmony_ci break; 1599bf215546Sopenharmony_ci case SpvStorageClassIncomingCallableDataKHR: 1600bf215546Sopenharmony_ci mode = vtn_variable_mode_call_data_in; 1601bf215546Sopenharmony_ci nir_mode = nir_var_shader_call_data; 1602bf215546Sopenharmony_ci break; 1603bf215546Sopenharmony_ci case SpvStorageClassRayPayloadKHR: 1604bf215546Sopenharmony_ci mode = vtn_variable_mode_ray_payload; 1605bf215546Sopenharmony_ci nir_mode = nir_var_shader_temp; 1606bf215546Sopenharmony_ci break; 1607bf215546Sopenharmony_ci case SpvStorageClassIncomingRayPayloadKHR: 1608bf215546Sopenharmony_ci mode = vtn_variable_mode_ray_payload_in; 1609bf215546Sopenharmony_ci nir_mode = nir_var_shader_call_data; 1610bf215546Sopenharmony_ci break; 1611bf215546Sopenharmony_ci case SpvStorageClassHitAttributeKHR: 1612bf215546Sopenharmony_ci mode = vtn_variable_mode_hit_attrib; 1613bf215546Sopenharmony_ci nir_mode = nir_var_ray_hit_attrib; 1614bf215546Sopenharmony_ci break; 1615bf215546Sopenharmony_ci case SpvStorageClassShaderRecordBufferKHR: 1616bf215546Sopenharmony_ci mode = vtn_variable_mode_shader_record; 1617bf215546Sopenharmony_ci nir_mode = nir_var_mem_constant; 1618bf215546Sopenharmony_ci break; 1619bf215546Sopenharmony_ci 1620bf215546Sopenharmony_ci case SpvStorageClassGeneric: 1621bf215546Sopenharmony_ci mode = vtn_variable_mode_generic; 1622bf215546Sopenharmony_ci nir_mode = nir_var_mem_generic; 1623bf215546Sopenharmony_ci break; 1624bf215546Sopenharmony_ci default: 1625bf215546Sopenharmony_ci vtn_fail("Unhandled variable storage class: %s (%u)", 1626bf215546Sopenharmony_ci spirv_storageclass_to_string(class), class); 1627bf215546Sopenharmony_ci } 1628bf215546Sopenharmony_ci 1629bf215546Sopenharmony_ci if (nir_mode_out) 1630bf215546Sopenharmony_ci *nir_mode_out = nir_mode; 1631bf215546Sopenharmony_ci 1632bf215546Sopenharmony_ci return mode; 1633bf215546Sopenharmony_ci} 1634bf215546Sopenharmony_ci 1635bf215546Sopenharmony_cinir_address_format 1636bf215546Sopenharmony_civtn_mode_to_address_format(struct vtn_builder *b, enum vtn_variable_mode mode) 1637bf215546Sopenharmony_ci{ 1638bf215546Sopenharmony_ci switch (mode) { 1639bf215546Sopenharmony_ci case vtn_variable_mode_ubo: 1640bf215546Sopenharmony_ci return b->options->ubo_addr_format; 1641bf215546Sopenharmony_ci 1642bf215546Sopenharmony_ci case vtn_variable_mode_ssbo: 1643bf215546Sopenharmony_ci return b->options->ssbo_addr_format; 1644bf215546Sopenharmony_ci 1645bf215546Sopenharmony_ci case vtn_variable_mode_phys_ssbo: 1646bf215546Sopenharmony_ci return b->options->phys_ssbo_addr_format; 1647bf215546Sopenharmony_ci 1648bf215546Sopenharmony_ci case vtn_variable_mode_push_constant: 1649bf215546Sopenharmony_ci return b->options->push_const_addr_format; 1650bf215546Sopenharmony_ci 1651bf215546Sopenharmony_ci case vtn_variable_mode_workgroup: 1652bf215546Sopenharmony_ci return b->options->shared_addr_format; 1653bf215546Sopenharmony_ci 1654bf215546Sopenharmony_ci case vtn_variable_mode_generic: 1655bf215546Sopenharmony_ci case vtn_variable_mode_cross_workgroup: 1656bf215546Sopenharmony_ci return b->options->global_addr_format; 1657bf215546Sopenharmony_ci 1658bf215546Sopenharmony_ci case vtn_variable_mode_shader_record: 1659bf215546Sopenharmony_ci case vtn_variable_mode_constant: 1660bf215546Sopenharmony_ci return b->options->constant_addr_format; 1661bf215546Sopenharmony_ci 1662bf215546Sopenharmony_ci case vtn_variable_mode_accel_struct: 1663bf215546Sopenharmony_ci return nir_address_format_64bit_global; 1664bf215546Sopenharmony_ci 1665bf215546Sopenharmony_ci case vtn_variable_mode_task_payload: 1666bf215546Sopenharmony_ci return b->options->task_payload_addr_format; 1667bf215546Sopenharmony_ci 1668bf215546Sopenharmony_ci case vtn_variable_mode_function: 1669bf215546Sopenharmony_ci if (b->physical_ptrs) 1670bf215546Sopenharmony_ci return b->options->temp_addr_format; 1671bf215546Sopenharmony_ci FALLTHROUGH; 1672bf215546Sopenharmony_ci 1673bf215546Sopenharmony_ci case vtn_variable_mode_private: 1674bf215546Sopenharmony_ci case vtn_variable_mode_uniform: 1675bf215546Sopenharmony_ci case vtn_variable_mode_atomic_counter: 1676bf215546Sopenharmony_ci case vtn_variable_mode_input: 1677bf215546Sopenharmony_ci case vtn_variable_mode_output: 1678bf215546Sopenharmony_ci case vtn_variable_mode_image: 1679bf215546Sopenharmony_ci case vtn_variable_mode_call_data: 1680bf215546Sopenharmony_ci case vtn_variable_mode_call_data_in: 1681bf215546Sopenharmony_ci case vtn_variable_mode_ray_payload: 1682bf215546Sopenharmony_ci case vtn_variable_mode_ray_payload_in: 1683bf215546Sopenharmony_ci case vtn_variable_mode_hit_attrib: 1684bf215546Sopenharmony_ci return nir_address_format_logical; 1685bf215546Sopenharmony_ci } 1686bf215546Sopenharmony_ci 1687bf215546Sopenharmony_ci unreachable("Invalid variable mode"); 1688bf215546Sopenharmony_ci} 1689bf215546Sopenharmony_ci 1690bf215546Sopenharmony_cinir_ssa_def * 1691bf215546Sopenharmony_civtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr) 1692bf215546Sopenharmony_ci{ 1693bf215546Sopenharmony_ci if ((vtn_pointer_is_external_block(b, ptr) && 1694bf215546Sopenharmony_ci vtn_type_contains_block(b, ptr->type) && 1695bf215546Sopenharmony_ci ptr->mode != vtn_variable_mode_phys_ssbo) || 1696bf215546Sopenharmony_ci ptr->mode == vtn_variable_mode_accel_struct) { 1697bf215546Sopenharmony_ci /* In this case, we're looking for a block index and not an actual 1698bf215546Sopenharmony_ci * deref. 1699bf215546Sopenharmony_ci * 1700bf215546Sopenharmony_ci * For PhysicalStorageBuffer pointers, we don't have a block index 1701bf215546Sopenharmony_ci * at all because we get the pointer directly from the client. This 1702bf215546Sopenharmony_ci * assumes that there will never be a SSBO binding variable using the 1703bf215546Sopenharmony_ci * PhysicalStorageBuffer storage class. This assumption appears 1704bf215546Sopenharmony_ci * to be correct according to the Vulkan spec because the table, 1705bf215546Sopenharmony_ci * "Shader Resource and Storage Class Correspondence," the only the 1706bf215546Sopenharmony_ci * Uniform storage class with BufferBlock or the StorageBuffer 1707bf215546Sopenharmony_ci * storage class with Block can be used. 1708bf215546Sopenharmony_ci */ 1709bf215546Sopenharmony_ci if (!ptr->block_index) { 1710bf215546Sopenharmony_ci /* If we don't have a block_index then we must be a pointer to the 1711bf215546Sopenharmony_ci * variable itself. 1712bf215546Sopenharmony_ci */ 1713bf215546Sopenharmony_ci vtn_assert(!ptr->deref); 1714bf215546Sopenharmony_ci 1715bf215546Sopenharmony_ci struct vtn_access_chain chain = { 1716bf215546Sopenharmony_ci .length = 0, 1717bf215546Sopenharmony_ci }; 1718bf215546Sopenharmony_ci ptr = vtn_pointer_dereference(b, ptr, &chain); 1719bf215546Sopenharmony_ci } 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci return ptr->block_index; 1722bf215546Sopenharmony_ci } else { 1723bf215546Sopenharmony_ci return &vtn_pointer_to_deref(b, ptr)->dest.ssa; 1724bf215546Sopenharmony_ci } 1725bf215546Sopenharmony_ci} 1726bf215546Sopenharmony_ci 1727bf215546Sopenharmony_cistruct vtn_pointer * 1728bf215546Sopenharmony_civtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa, 1729bf215546Sopenharmony_ci struct vtn_type *ptr_type) 1730bf215546Sopenharmony_ci{ 1731bf215546Sopenharmony_ci vtn_assert(ptr_type->base_type == vtn_base_type_pointer); 1732bf215546Sopenharmony_ci 1733bf215546Sopenharmony_ci struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer); 1734bf215546Sopenharmony_ci struct vtn_type *without_array = 1735bf215546Sopenharmony_ci vtn_type_without_array(ptr_type->deref); 1736bf215546Sopenharmony_ci 1737bf215546Sopenharmony_ci nir_variable_mode nir_mode; 1738bf215546Sopenharmony_ci ptr->mode = vtn_storage_class_to_mode(b, ptr_type->storage_class, 1739bf215546Sopenharmony_ci without_array, &nir_mode); 1740bf215546Sopenharmony_ci ptr->type = ptr_type->deref; 1741bf215546Sopenharmony_ci ptr->ptr_type = ptr_type; 1742bf215546Sopenharmony_ci 1743bf215546Sopenharmony_ci const struct glsl_type *deref_type = 1744bf215546Sopenharmony_ci vtn_type_get_nir_type(b, ptr_type->deref, ptr->mode); 1745bf215546Sopenharmony_ci if (!vtn_pointer_is_external_block(b, ptr) && 1746bf215546Sopenharmony_ci ptr->mode != vtn_variable_mode_accel_struct) { 1747bf215546Sopenharmony_ci ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode, 1748bf215546Sopenharmony_ci deref_type, ptr_type->stride); 1749bf215546Sopenharmony_ci } else if ((vtn_type_contains_block(b, ptr->type) && 1750bf215546Sopenharmony_ci ptr->mode != vtn_variable_mode_phys_ssbo) || 1751bf215546Sopenharmony_ci ptr->mode == vtn_variable_mode_accel_struct) { 1752bf215546Sopenharmony_ci /* This is a pointer to somewhere in an array of blocks, not a 1753bf215546Sopenharmony_ci * pointer to somewhere inside the block. Set the block index 1754bf215546Sopenharmony_ci * instead of making a cast. 1755bf215546Sopenharmony_ci */ 1756bf215546Sopenharmony_ci ptr->block_index = ssa; 1757bf215546Sopenharmony_ci } else { 1758bf215546Sopenharmony_ci /* This is a pointer to something internal or a pointer inside a 1759bf215546Sopenharmony_ci * block. It's just a regular cast. 1760bf215546Sopenharmony_ci * 1761bf215546Sopenharmony_ci * For PhysicalStorageBuffer pointers, we don't have a block index 1762bf215546Sopenharmony_ci * at all because we get the pointer directly from the client. This 1763bf215546Sopenharmony_ci * assumes that there will never be a SSBO binding variable using the 1764bf215546Sopenharmony_ci * PhysicalStorageBuffer storage class. This assumption appears 1765bf215546Sopenharmony_ci * to be correct according to the Vulkan spec because the table, 1766bf215546Sopenharmony_ci * "Shader Resource and Storage Class Correspondence," the only the 1767bf215546Sopenharmony_ci * Uniform storage class with BufferBlock or the StorageBuffer 1768bf215546Sopenharmony_ci * storage class with Block can be used. 1769bf215546Sopenharmony_ci */ 1770bf215546Sopenharmony_ci ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode, 1771bf215546Sopenharmony_ci deref_type, ptr_type->stride); 1772bf215546Sopenharmony_ci ptr->deref->dest.ssa.num_components = 1773bf215546Sopenharmony_ci glsl_get_vector_elements(ptr_type->type); 1774bf215546Sopenharmony_ci ptr->deref->dest.ssa.bit_size = glsl_get_bit_size(ptr_type->type); 1775bf215546Sopenharmony_ci } 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ci return ptr; 1778bf215546Sopenharmony_ci} 1779bf215546Sopenharmony_ci 1780bf215546Sopenharmony_cistatic void 1781bf215546Sopenharmony_ciassign_missing_member_locations(struct vtn_variable *var) 1782bf215546Sopenharmony_ci{ 1783bf215546Sopenharmony_ci unsigned length = 1784bf215546Sopenharmony_ci glsl_get_length(glsl_without_array(var->type->type)); 1785bf215546Sopenharmony_ci int location = var->base_location; 1786bf215546Sopenharmony_ci 1787bf215546Sopenharmony_ci for (unsigned i = 0; i < length; i++) { 1788bf215546Sopenharmony_ci /* From the Vulkan spec: 1789bf215546Sopenharmony_ci * 1790bf215546Sopenharmony_ci * “If the structure type is a Block but without a Location, then each 1791bf215546Sopenharmony_ci * of its members must have a Location decoration.” 1792bf215546Sopenharmony_ci * 1793bf215546Sopenharmony_ci */ 1794bf215546Sopenharmony_ci if (var->type->block) { 1795bf215546Sopenharmony_ci assert(var->base_location != -1 || 1796bf215546Sopenharmony_ci var->var->members[i].location != -1); 1797bf215546Sopenharmony_ci } 1798bf215546Sopenharmony_ci 1799bf215546Sopenharmony_ci /* From the Vulkan spec: 1800bf215546Sopenharmony_ci * 1801bf215546Sopenharmony_ci * “Any member with its own Location decoration is assigned that 1802bf215546Sopenharmony_ci * location. Each remaining member is assigned the location after the 1803bf215546Sopenharmony_ci * immediately preceding member in declaration order.” 1804bf215546Sopenharmony_ci */ 1805bf215546Sopenharmony_ci if (var->var->members[i].location != -1) 1806bf215546Sopenharmony_ci location = var->var->members[i].location; 1807bf215546Sopenharmony_ci else 1808bf215546Sopenharmony_ci var->var->members[i].location = location; 1809bf215546Sopenharmony_ci 1810bf215546Sopenharmony_ci /* Below we use type instead of interface_type, because interface_type 1811bf215546Sopenharmony_ci * is only available when it is a Block. This code also supports 1812bf215546Sopenharmony_ci * input/outputs that are just structs 1813bf215546Sopenharmony_ci */ 1814bf215546Sopenharmony_ci const struct glsl_type *member_type = 1815bf215546Sopenharmony_ci glsl_get_struct_field(glsl_without_array(var->type->type), i); 1816bf215546Sopenharmony_ci 1817bf215546Sopenharmony_ci location += 1818bf215546Sopenharmony_ci glsl_count_attribute_slots(member_type, 1819bf215546Sopenharmony_ci false /* is_gl_vertex_input */); 1820bf215546Sopenharmony_ci } 1821bf215546Sopenharmony_ci} 1822bf215546Sopenharmony_ci 1823bf215546Sopenharmony_cinir_deref_instr * 1824bf215546Sopenharmony_civtn_get_call_payload_for_location(struct vtn_builder *b, uint32_t location_id) 1825bf215546Sopenharmony_ci{ 1826bf215546Sopenharmony_ci uint32_t location = vtn_constant_uint(b, location_id); 1827bf215546Sopenharmony_ci nir_foreach_variable_with_modes(var, b->nb.shader, nir_var_shader_temp) { 1828bf215546Sopenharmony_ci if (var->data.explicit_location && 1829bf215546Sopenharmony_ci var->data.location == location) 1830bf215546Sopenharmony_ci return nir_build_deref_var(&b->nb, var); 1831bf215546Sopenharmony_ci } 1832bf215546Sopenharmony_ci vtn_fail("Couldn't find variable with a storage class of CallableDataKHR " 1833bf215546Sopenharmony_ci "or RayPayloadKHR and location %d", location); 1834bf215546Sopenharmony_ci} 1835bf215546Sopenharmony_ci 1836bf215546Sopenharmony_cistatic bool 1837bf215546Sopenharmony_civtn_type_is_ray_query(struct vtn_type *type) 1838bf215546Sopenharmony_ci{ 1839bf215546Sopenharmony_ci return vtn_type_without_array(type)->base_type == vtn_base_type_ray_query; 1840bf215546Sopenharmony_ci} 1841bf215546Sopenharmony_ci 1842bf215546Sopenharmony_cistatic void 1843bf215546Sopenharmony_civtn_create_variable(struct vtn_builder *b, struct vtn_value *val, 1844bf215546Sopenharmony_ci struct vtn_type *ptr_type, SpvStorageClass storage_class, 1845bf215546Sopenharmony_ci struct vtn_value *initializer) 1846bf215546Sopenharmony_ci{ 1847bf215546Sopenharmony_ci vtn_assert(ptr_type->base_type == vtn_base_type_pointer); 1848bf215546Sopenharmony_ci struct vtn_type *type = ptr_type->deref; 1849bf215546Sopenharmony_ci 1850bf215546Sopenharmony_ci struct vtn_type *without_array = vtn_type_without_array(ptr_type->deref); 1851bf215546Sopenharmony_ci 1852bf215546Sopenharmony_ci enum vtn_variable_mode mode; 1853bf215546Sopenharmony_ci nir_variable_mode nir_mode; 1854bf215546Sopenharmony_ci mode = vtn_storage_class_to_mode(b, storage_class, without_array, &nir_mode); 1855bf215546Sopenharmony_ci 1856bf215546Sopenharmony_ci switch (mode) { 1857bf215546Sopenharmony_ci case vtn_variable_mode_ubo: 1858bf215546Sopenharmony_ci /* There's no other way to get vtn_variable_mode_ubo */ 1859bf215546Sopenharmony_ci vtn_assert(without_array->block); 1860bf215546Sopenharmony_ci break; 1861bf215546Sopenharmony_ci case vtn_variable_mode_ssbo: 1862bf215546Sopenharmony_ci if (storage_class == SpvStorageClassStorageBuffer && 1863bf215546Sopenharmony_ci !without_array->block) { 1864bf215546Sopenharmony_ci if (b->variable_pointers) { 1865bf215546Sopenharmony_ci vtn_fail("Variables in the StorageBuffer storage class must " 1866bf215546Sopenharmony_ci "have a struct type with the Block decoration"); 1867bf215546Sopenharmony_ci } else { 1868bf215546Sopenharmony_ci /* If variable pointers are not present, it's still malformed 1869bf215546Sopenharmony_ci * SPIR-V but we can parse it and do the right thing anyway. 1870bf215546Sopenharmony_ci * Since some of the 8-bit storage tests have bugs in this are, 1871bf215546Sopenharmony_ci * just make it a warning for now. 1872bf215546Sopenharmony_ci */ 1873bf215546Sopenharmony_ci vtn_warn("Variables in the StorageBuffer storage class must " 1874bf215546Sopenharmony_ci "have a struct type with the Block decoration"); 1875bf215546Sopenharmony_ci } 1876bf215546Sopenharmony_ci } 1877bf215546Sopenharmony_ci break; 1878bf215546Sopenharmony_ci 1879bf215546Sopenharmony_ci case vtn_variable_mode_generic: 1880bf215546Sopenharmony_ci vtn_fail("Cannot create a variable with the Generic storage class"); 1881bf215546Sopenharmony_ci break; 1882bf215546Sopenharmony_ci 1883bf215546Sopenharmony_ci case vtn_variable_mode_image: 1884bf215546Sopenharmony_ci if (storage_class == SpvStorageClassImage) 1885bf215546Sopenharmony_ci vtn_fail("Cannot create a variable with the Image storage class"); 1886bf215546Sopenharmony_ci else 1887bf215546Sopenharmony_ci vtn_assert(storage_class == SpvStorageClassUniformConstant); 1888bf215546Sopenharmony_ci break; 1889bf215546Sopenharmony_ci 1890bf215546Sopenharmony_ci case vtn_variable_mode_phys_ssbo: 1891bf215546Sopenharmony_ci vtn_fail("Cannot create a variable with the " 1892bf215546Sopenharmony_ci "PhysicalStorageBuffer storage class"); 1893bf215546Sopenharmony_ci break; 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_ci default: 1896bf215546Sopenharmony_ci /* No tallying is needed */ 1897bf215546Sopenharmony_ci break; 1898bf215546Sopenharmony_ci } 1899bf215546Sopenharmony_ci 1900bf215546Sopenharmony_ci struct vtn_variable *var = rzalloc(b, struct vtn_variable); 1901bf215546Sopenharmony_ci var->type = type; 1902bf215546Sopenharmony_ci var->mode = mode; 1903bf215546Sopenharmony_ci var->base_location = -1; 1904bf215546Sopenharmony_ci 1905bf215546Sopenharmony_ci val->pointer = rzalloc(b, struct vtn_pointer); 1906bf215546Sopenharmony_ci val->pointer->mode = var->mode; 1907bf215546Sopenharmony_ci val->pointer->type = var->type; 1908bf215546Sopenharmony_ci val->pointer->ptr_type = ptr_type; 1909bf215546Sopenharmony_ci val->pointer->var = var; 1910bf215546Sopenharmony_ci val->pointer->access = var->type->access; 1911bf215546Sopenharmony_ci 1912bf215546Sopenharmony_ci switch (var->mode) { 1913bf215546Sopenharmony_ci case vtn_variable_mode_function: 1914bf215546Sopenharmony_ci case vtn_variable_mode_private: 1915bf215546Sopenharmony_ci case vtn_variable_mode_uniform: 1916bf215546Sopenharmony_ci case vtn_variable_mode_atomic_counter: 1917bf215546Sopenharmony_ci case vtn_variable_mode_constant: 1918bf215546Sopenharmony_ci case vtn_variable_mode_call_data: 1919bf215546Sopenharmony_ci case vtn_variable_mode_call_data_in: 1920bf215546Sopenharmony_ci case vtn_variable_mode_image: 1921bf215546Sopenharmony_ci case vtn_variable_mode_ray_payload: 1922bf215546Sopenharmony_ci case vtn_variable_mode_ray_payload_in: 1923bf215546Sopenharmony_ci case vtn_variable_mode_hit_attrib: 1924bf215546Sopenharmony_ci /* For these, we create the variable normally */ 1925bf215546Sopenharmony_ci var->var = rzalloc(b->shader, nir_variable); 1926bf215546Sopenharmony_ci var->var->name = ralloc_strdup(var->var, val->name); 1927bf215546Sopenharmony_ci var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); 1928bf215546Sopenharmony_ci 1929bf215546Sopenharmony_ci /* This is a total hack but we need some way to flag variables which are 1930bf215546Sopenharmony_ci * going to be call payloads. See get_call_payload_deref. 1931bf215546Sopenharmony_ci */ 1932bf215546Sopenharmony_ci if (storage_class == SpvStorageClassCallableDataKHR || 1933bf215546Sopenharmony_ci storage_class == SpvStorageClassRayPayloadKHR) 1934bf215546Sopenharmony_ci var->var->data.explicit_location = true; 1935bf215546Sopenharmony_ci 1936bf215546Sopenharmony_ci var->var->data.mode = nir_mode; 1937bf215546Sopenharmony_ci var->var->data.location = -1; 1938bf215546Sopenharmony_ci var->var->data.ray_query = vtn_type_is_ray_query(var->type); 1939bf215546Sopenharmony_ci var->var->interface_type = NULL; 1940bf215546Sopenharmony_ci break; 1941bf215546Sopenharmony_ci 1942bf215546Sopenharmony_ci case vtn_variable_mode_ubo: 1943bf215546Sopenharmony_ci case vtn_variable_mode_ssbo: 1944bf215546Sopenharmony_ci case vtn_variable_mode_push_constant: 1945bf215546Sopenharmony_ci case vtn_variable_mode_accel_struct: 1946bf215546Sopenharmony_ci case vtn_variable_mode_shader_record: 1947bf215546Sopenharmony_ci var->var = rzalloc(b->shader, nir_variable); 1948bf215546Sopenharmony_ci var->var->name = ralloc_strdup(var->var, val->name); 1949bf215546Sopenharmony_ci 1950bf215546Sopenharmony_ci var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); 1951bf215546Sopenharmony_ci var->var->interface_type = var->var->type; 1952bf215546Sopenharmony_ci 1953bf215546Sopenharmony_ci var->var->data.mode = nir_mode; 1954bf215546Sopenharmony_ci var->var->data.location = -1; 1955bf215546Sopenharmony_ci var->var->data.driver_location = 0; 1956bf215546Sopenharmony_ci var->var->data.access = var->type->access; 1957bf215546Sopenharmony_ci break; 1958bf215546Sopenharmony_ci 1959bf215546Sopenharmony_ci case vtn_variable_mode_workgroup: 1960bf215546Sopenharmony_ci case vtn_variable_mode_cross_workgroup: 1961bf215546Sopenharmony_ci case vtn_variable_mode_task_payload: 1962bf215546Sopenharmony_ci /* Create the variable normally */ 1963bf215546Sopenharmony_ci var->var = rzalloc(b->shader, nir_variable); 1964bf215546Sopenharmony_ci var->var->name = ralloc_strdup(var->var, val->name); 1965bf215546Sopenharmony_ci var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); 1966bf215546Sopenharmony_ci var->var->data.mode = nir_mode; 1967bf215546Sopenharmony_ci break; 1968bf215546Sopenharmony_ci 1969bf215546Sopenharmony_ci case vtn_variable_mode_input: 1970bf215546Sopenharmony_ci case vtn_variable_mode_output: { 1971bf215546Sopenharmony_ci var->var = rzalloc(b->shader, nir_variable); 1972bf215546Sopenharmony_ci var->var->name = ralloc_strdup(var->var, val->name); 1973bf215546Sopenharmony_ci var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); 1974bf215546Sopenharmony_ci var->var->data.mode = nir_mode; 1975bf215546Sopenharmony_ci 1976bf215546Sopenharmony_ci /* In order to know whether or not we're a per-vertex inout, we need 1977bf215546Sopenharmony_ci * the patch qualifier. This means walking the variable decorations 1978bf215546Sopenharmony_ci * early before we actually create any variables. Not a big deal. 1979bf215546Sopenharmony_ci * 1980bf215546Sopenharmony_ci * GLSLang really likes to place decorations in the most interior 1981bf215546Sopenharmony_ci * thing it possibly can. In particular, if you have a struct, it 1982bf215546Sopenharmony_ci * will place the patch decorations on the struct members. This 1983bf215546Sopenharmony_ci * should be handled by the variable splitting below just fine. 1984bf215546Sopenharmony_ci * 1985bf215546Sopenharmony_ci * If you have an array-of-struct, things get even more weird as it 1986bf215546Sopenharmony_ci * will place the patch decorations on the struct even though it's 1987bf215546Sopenharmony_ci * inside an array and some of the members being patch and others not 1988bf215546Sopenharmony_ci * makes no sense whatsoever. Since the only sensible thing is for 1989bf215546Sopenharmony_ci * it to be all or nothing, we'll call it patch if any of the members 1990bf215546Sopenharmony_ci * are declared patch. 1991bf215546Sopenharmony_ci */ 1992bf215546Sopenharmony_ci vtn_foreach_decoration(b, val, gather_var_kind_cb, var); 1993bf215546Sopenharmony_ci if (glsl_type_is_array(var->type->type) && 1994bf215546Sopenharmony_ci glsl_type_is_struct_or_ifc(without_array->type)) { 1995bf215546Sopenharmony_ci vtn_foreach_decoration(b, vtn_value(b, without_array->id, 1996bf215546Sopenharmony_ci vtn_value_type_type), 1997bf215546Sopenharmony_ci gather_var_kind_cb, var); 1998bf215546Sopenharmony_ci } 1999bf215546Sopenharmony_ci 2000bf215546Sopenharmony_ci struct vtn_type *per_vertex_type = var->type; 2001bf215546Sopenharmony_ci if (nir_is_arrayed_io(var->var, b->shader->info.stage)) 2002bf215546Sopenharmony_ci per_vertex_type = var->type->array_element; 2003bf215546Sopenharmony_ci 2004bf215546Sopenharmony_ci /* Figure out the interface block type. */ 2005bf215546Sopenharmony_ci struct vtn_type *iface_type = per_vertex_type; 2006bf215546Sopenharmony_ci if (var->mode == vtn_variable_mode_output && 2007bf215546Sopenharmony_ci (b->shader->info.stage == MESA_SHADER_VERTEX || 2008bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_TESS_EVAL || 2009bf215546Sopenharmony_ci b->shader->info.stage == MESA_SHADER_GEOMETRY)) { 2010bf215546Sopenharmony_ci /* For vertex data outputs, we can end up with arrays of blocks for 2011bf215546Sopenharmony_ci * transform feedback where each array element corresponds to a 2012bf215546Sopenharmony_ci * different XFB output buffer. 2013bf215546Sopenharmony_ci */ 2014bf215546Sopenharmony_ci while (iface_type->base_type == vtn_base_type_array) 2015bf215546Sopenharmony_ci iface_type = iface_type->array_element; 2016bf215546Sopenharmony_ci } 2017bf215546Sopenharmony_ci if (iface_type->base_type == vtn_base_type_struct && iface_type->block) 2018bf215546Sopenharmony_ci var->var->interface_type = vtn_type_get_nir_type(b, iface_type, 2019bf215546Sopenharmony_ci var->mode); 2020bf215546Sopenharmony_ci 2021bf215546Sopenharmony_ci /* If it's a block, set it up as per-member so can be splitted later by 2022bf215546Sopenharmony_ci * nir_split_per_member_structs. 2023bf215546Sopenharmony_ci * 2024bf215546Sopenharmony_ci * This is for a couple of reasons. For one, builtins may all come in a 2025bf215546Sopenharmony_ci * block and we really want those split out into separate variables. 2026bf215546Sopenharmony_ci * For another, interpolation qualifiers can be applied to members of 2027bf215546Sopenharmony_ci * the top-level struct and we need to be able to preserve that 2028bf215546Sopenharmony_ci * information. 2029bf215546Sopenharmony_ci */ 2030bf215546Sopenharmony_ci if (per_vertex_type->base_type == vtn_base_type_struct && 2031bf215546Sopenharmony_ci per_vertex_type->block) { 2032bf215546Sopenharmony_ci var->var->num_members = glsl_get_length(per_vertex_type->type); 2033bf215546Sopenharmony_ci var->var->members = rzalloc_array(var->var, struct nir_variable_data, 2034bf215546Sopenharmony_ci var->var->num_members); 2035bf215546Sopenharmony_ci 2036bf215546Sopenharmony_ci for (unsigned i = 0; i < var->var->num_members; i++) { 2037bf215546Sopenharmony_ci var->var->members[i].mode = nir_mode; 2038bf215546Sopenharmony_ci var->var->members[i].patch = var->var->data.patch; 2039bf215546Sopenharmony_ci var->var->members[i].location = -1; 2040bf215546Sopenharmony_ci } 2041bf215546Sopenharmony_ci } 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci /* For inputs and outputs, we need to grab locations and builtin 2044bf215546Sopenharmony_ci * information from the per-vertex type. 2045bf215546Sopenharmony_ci */ 2046bf215546Sopenharmony_ci vtn_foreach_decoration(b, vtn_value(b, per_vertex_type->id, 2047bf215546Sopenharmony_ci vtn_value_type_type), 2048bf215546Sopenharmony_ci var_decoration_cb, var); 2049bf215546Sopenharmony_ci 2050bf215546Sopenharmony_ci break; 2051bf215546Sopenharmony_ci } 2052bf215546Sopenharmony_ci 2053bf215546Sopenharmony_ci case vtn_variable_mode_phys_ssbo: 2054bf215546Sopenharmony_ci case vtn_variable_mode_generic: 2055bf215546Sopenharmony_ci unreachable("Should have been caught before"); 2056bf215546Sopenharmony_ci } 2057bf215546Sopenharmony_ci 2058bf215546Sopenharmony_ci /* Ignore incorrectly generated Undef initializers. */ 2059bf215546Sopenharmony_ci if (b->wa_llvm_spirv_ignore_workgroup_initializer && 2060bf215546Sopenharmony_ci initializer && 2061bf215546Sopenharmony_ci storage_class == SpvStorageClassWorkgroup) 2062bf215546Sopenharmony_ci initializer = NULL; 2063bf215546Sopenharmony_ci 2064bf215546Sopenharmony_ci /* Only initialize variable when there is an initializer and it's not 2065bf215546Sopenharmony_ci * undef. 2066bf215546Sopenharmony_ci */ 2067bf215546Sopenharmony_ci if (initializer && !initializer->is_undef_constant) { 2068bf215546Sopenharmony_ci switch (storage_class) { 2069bf215546Sopenharmony_ci case SpvStorageClassWorkgroup: 2070bf215546Sopenharmony_ci /* VK_KHR_zero_initialize_workgroup_memory. */ 2071bf215546Sopenharmony_ci vtn_fail_if(b->options->environment != NIR_SPIRV_VULKAN, 2072bf215546Sopenharmony_ci "Only Vulkan supports variable initializer " 2073bf215546Sopenharmony_ci "for Workgroup variable %u", 2074bf215546Sopenharmony_ci vtn_id_for_value(b, val)); 2075bf215546Sopenharmony_ci vtn_fail_if(initializer->value_type != vtn_value_type_constant || 2076bf215546Sopenharmony_ci !initializer->is_null_constant, 2077bf215546Sopenharmony_ci "Workgroup variable %u can only have OpConstantNull " 2078bf215546Sopenharmony_ci "as initializer, but have %u instead", 2079bf215546Sopenharmony_ci vtn_id_for_value(b, val), 2080bf215546Sopenharmony_ci vtn_id_for_value(b, initializer)); 2081bf215546Sopenharmony_ci b->shader->info.zero_initialize_shared_memory = true; 2082bf215546Sopenharmony_ci break; 2083bf215546Sopenharmony_ci 2084bf215546Sopenharmony_ci case SpvStorageClassUniformConstant: 2085bf215546Sopenharmony_ci vtn_fail_if(b->options->environment != NIR_SPIRV_OPENGL && 2086bf215546Sopenharmony_ci b->options->environment != NIR_SPIRV_OPENCL, 2087bf215546Sopenharmony_ci "Only OpenGL and OpenCL support variable initializer " 2088bf215546Sopenharmony_ci "for UniformConstant variable %u\n", 2089bf215546Sopenharmony_ci vtn_id_for_value(b, val)); 2090bf215546Sopenharmony_ci vtn_fail_if(initializer->value_type != vtn_value_type_constant, 2091bf215546Sopenharmony_ci "UniformConstant variable %u can only have a constant " 2092bf215546Sopenharmony_ci "initializer, but have %u instead", 2093bf215546Sopenharmony_ci vtn_id_for_value(b, val), 2094bf215546Sopenharmony_ci vtn_id_for_value(b, initializer)); 2095bf215546Sopenharmony_ci break; 2096bf215546Sopenharmony_ci 2097bf215546Sopenharmony_ci case SpvStorageClassOutput: 2098bf215546Sopenharmony_ci case SpvStorageClassPrivate: 2099bf215546Sopenharmony_ci vtn_assert(b->options->environment != NIR_SPIRV_OPENCL); 2100bf215546Sopenharmony_ci /* These can have any initializer. */ 2101bf215546Sopenharmony_ci break; 2102bf215546Sopenharmony_ci 2103bf215546Sopenharmony_ci case SpvStorageClassFunction: 2104bf215546Sopenharmony_ci /* These can have any initializer. */ 2105bf215546Sopenharmony_ci break; 2106bf215546Sopenharmony_ci 2107bf215546Sopenharmony_ci case SpvStorageClassCrossWorkgroup: 2108bf215546Sopenharmony_ci vtn_assert(b->options->environment == NIR_SPIRV_OPENCL); 2109bf215546Sopenharmony_ci vtn_fail("Initializer for CrossWorkgroup variable %u " 2110bf215546Sopenharmony_ci "not yet supported in Mesa.", 2111bf215546Sopenharmony_ci vtn_id_for_value(b, val)); 2112bf215546Sopenharmony_ci break; 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_ci default: { 2115bf215546Sopenharmony_ci const enum nir_spirv_execution_environment env = 2116bf215546Sopenharmony_ci b->options->environment; 2117bf215546Sopenharmony_ci const char *env_name = 2118bf215546Sopenharmony_ci env == NIR_SPIRV_VULKAN ? "Vulkan" : 2119bf215546Sopenharmony_ci env == NIR_SPIRV_OPENCL ? "OpenCL" : 2120bf215546Sopenharmony_ci env == NIR_SPIRV_OPENGL ? "OpenGL" : 2121bf215546Sopenharmony_ci NULL; 2122bf215546Sopenharmony_ci vtn_assert(env_name); 2123bf215546Sopenharmony_ci vtn_fail("In %s, any OpVariable with an Initializer operand " 2124bf215546Sopenharmony_ci "must have %s%s%s, or Function as " 2125bf215546Sopenharmony_ci "its Storage Class operand. Variable %u has an " 2126bf215546Sopenharmony_ci "Initializer but its Storage Class is %s.", 2127bf215546Sopenharmony_ci env_name, 2128bf215546Sopenharmony_ci env == NIR_SPIRV_VULKAN ? "Private, Output, Workgroup" : "", 2129bf215546Sopenharmony_ci env == NIR_SPIRV_OPENCL ? "CrossWorkgroup, UniformConstant" : "", 2130bf215546Sopenharmony_ci env == NIR_SPIRV_OPENGL ? "Private, Output, UniformConstant" : "", 2131bf215546Sopenharmony_ci vtn_id_for_value(b, val), 2132bf215546Sopenharmony_ci spirv_storageclass_to_string(storage_class)); 2133bf215546Sopenharmony_ci } 2134bf215546Sopenharmony_ci } 2135bf215546Sopenharmony_ci 2136bf215546Sopenharmony_ci switch (initializer->value_type) { 2137bf215546Sopenharmony_ci case vtn_value_type_constant: 2138bf215546Sopenharmony_ci var->var->constant_initializer = 2139bf215546Sopenharmony_ci nir_constant_clone(initializer->constant, var->var); 2140bf215546Sopenharmony_ci break; 2141bf215546Sopenharmony_ci case vtn_value_type_pointer: 2142bf215546Sopenharmony_ci var->var->pointer_initializer = initializer->pointer->var->var; 2143bf215546Sopenharmony_ci break; 2144bf215546Sopenharmony_ci default: 2145bf215546Sopenharmony_ci vtn_fail("SPIR-V variable initializer %u must be constant or pointer", 2146bf215546Sopenharmony_ci vtn_id_for_value(b, initializer)); 2147bf215546Sopenharmony_ci } 2148bf215546Sopenharmony_ci } 2149bf215546Sopenharmony_ci 2150bf215546Sopenharmony_ci if (var->mode == vtn_variable_mode_uniform || 2151bf215546Sopenharmony_ci var->mode == vtn_variable_mode_image || 2152bf215546Sopenharmony_ci var->mode == vtn_variable_mode_ssbo) { 2153bf215546Sopenharmony_ci /* SSBOs and images are assumed to not alias in the Simple, GLSL and Vulkan memory models */ 2154bf215546Sopenharmony_ci var->var->data.access |= b->mem_model != SpvMemoryModelOpenCL ? ACCESS_RESTRICT : 0; 2155bf215546Sopenharmony_ci } 2156bf215546Sopenharmony_ci 2157bf215546Sopenharmony_ci vtn_foreach_decoration(b, val, var_decoration_cb, var); 2158bf215546Sopenharmony_ci vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer); 2159bf215546Sopenharmony_ci 2160bf215546Sopenharmony_ci /* Propagate access flags from the OpVariable decorations. */ 2161bf215546Sopenharmony_ci val->pointer->access |= var->access; 2162bf215546Sopenharmony_ci 2163bf215546Sopenharmony_ci if ((var->mode == vtn_variable_mode_input || 2164bf215546Sopenharmony_ci var->mode == vtn_variable_mode_output) && 2165bf215546Sopenharmony_ci var->var->members) { 2166bf215546Sopenharmony_ci assign_missing_member_locations(var); 2167bf215546Sopenharmony_ci } 2168bf215546Sopenharmony_ci 2169bf215546Sopenharmony_ci if (var->mode == vtn_variable_mode_uniform || 2170bf215546Sopenharmony_ci var->mode == vtn_variable_mode_image || 2171bf215546Sopenharmony_ci var->mode == vtn_variable_mode_ubo || 2172bf215546Sopenharmony_ci var->mode == vtn_variable_mode_ssbo || 2173bf215546Sopenharmony_ci var->mode == vtn_variable_mode_atomic_counter) { 2174bf215546Sopenharmony_ci /* XXX: We still need the binding information in the nir_variable 2175bf215546Sopenharmony_ci * for these. We should fix that. 2176bf215546Sopenharmony_ci */ 2177bf215546Sopenharmony_ci var->var->data.binding = var->binding; 2178bf215546Sopenharmony_ci var->var->data.explicit_binding = var->explicit_binding; 2179bf215546Sopenharmony_ci var->var->data.descriptor_set = var->descriptor_set; 2180bf215546Sopenharmony_ci var->var->data.index = var->input_attachment_index; 2181bf215546Sopenharmony_ci var->var->data.offset = var->offset; 2182bf215546Sopenharmony_ci 2183bf215546Sopenharmony_ci if (glsl_type_is_image(glsl_without_array(var->var->type))) 2184bf215546Sopenharmony_ci var->var->data.image.format = without_array->image_format; 2185bf215546Sopenharmony_ci } 2186bf215546Sopenharmony_ci 2187bf215546Sopenharmony_ci if (var->mode == vtn_variable_mode_function) { 2188bf215546Sopenharmony_ci vtn_assert(var->var != NULL && var->var->members == NULL); 2189bf215546Sopenharmony_ci nir_function_impl_add_variable(b->nb.impl, var->var); 2190bf215546Sopenharmony_ci } else if (var->var) { 2191bf215546Sopenharmony_ci nir_shader_add_variable(b->shader, var->var); 2192bf215546Sopenharmony_ci } else { 2193bf215546Sopenharmony_ci vtn_assert(vtn_pointer_is_external_block(b, val->pointer) || 2194bf215546Sopenharmony_ci var->mode == vtn_variable_mode_accel_struct || 2195bf215546Sopenharmony_ci var->mode == vtn_variable_mode_shader_record); 2196bf215546Sopenharmony_ci } 2197bf215546Sopenharmony_ci} 2198bf215546Sopenharmony_ci 2199bf215546Sopenharmony_cistatic void 2200bf215546Sopenharmony_civtn_assert_types_equal(struct vtn_builder *b, SpvOp opcode, 2201bf215546Sopenharmony_ci struct vtn_type *dst_type, 2202bf215546Sopenharmony_ci struct vtn_type *src_type) 2203bf215546Sopenharmony_ci{ 2204bf215546Sopenharmony_ci if (dst_type->id == src_type->id) 2205bf215546Sopenharmony_ci return; 2206bf215546Sopenharmony_ci 2207bf215546Sopenharmony_ci if (vtn_types_compatible(b, dst_type, src_type)) { 2208bf215546Sopenharmony_ci /* Early versions of GLSLang would re-emit types unnecessarily and you 2209bf215546Sopenharmony_ci * would end up with OpLoad, OpStore, or OpCopyMemory opcodes which have 2210bf215546Sopenharmony_ci * mismatched source and destination types. 2211bf215546Sopenharmony_ci * 2212bf215546Sopenharmony_ci * https://github.com/KhronosGroup/glslang/issues/304 2213bf215546Sopenharmony_ci * https://github.com/KhronosGroup/glslang/issues/307 2214bf215546Sopenharmony_ci * https://bugs.freedesktop.org/show_bug.cgi?id=104338 2215bf215546Sopenharmony_ci * https://bugs.freedesktop.org/show_bug.cgi?id=104424 2216bf215546Sopenharmony_ci */ 2217bf215546Sopenharmony_ci vtn_warn("Source and destination types of %s do not have the same " 2218bf215546Sopenharmony_ci "ID (but are compatible): %u vs %u", 2219bf215546Sopenharmony_ci spirv_op_to_string(opcode), dst_type->id, src_type->id); 2220bf215546Sopenharmony_ci return; 2221bf215546Sopenharmony_ci } 2222bf215546Sopenharmony_ci 2223bf215546Sopenharmony_ci vtn_fail("Source and destination types of %s do not match: %s vs. %s", 2224bf215546Sopenharmony_ci spirv_op_to_string(opcode), 2225bf215546Sopenharmony_ci glsl_get_type_name(dst_type->type), 2226bf215546Sopenharmony_ci glsl_get_type_name(src_type->type)); 2227bf215546Sopenharmony_ci} 2228bf215546Sopenharmony_ci 2229bf215546Sopenharmony_cistatic nir_ssa_def * 2230bf215546Sopenharmony_cinir_shrink_zero_pad_vec(nir_builder *b, nir_ssa_def *val, 2231bf215546Sopenharmony_ci unsigned num_components) 2232bf215546Sopenharmony_ci{ 2233bf215546Sopenharmony_ci if (val->num_components == num_components) 2234bf215546Sopenharmony_ci return val; 2235bf215546Sopenharmony_ci 2236bf215546Sopenharmony_ci nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS]; 2237bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 2238bf215546Sopenharmony_ci if (i < val->num_components) 2239bf215546Sopenharmony_ci comps[i] = nir_channel(b, val, i); 2240bf215546Sopenharmony_ci else 2241bf215546Sopenharmony_ci comps[i] = nir_imm_intN_t(b, 0, val->bit_size); 2242bf215546Sopenharmony_ci } 2243bf215546Sopenharmony_ci return nir_vec(b, comps, num_components); 2244bf215546Sopenharmony_ci} 2245bf215546Sopenharmony_ci 2246bf215546Sopenharmony_cistatic nir_ssa_def * 2247bf215546Sopenharmony_cinir_sloppy_bitcast(nir_builder *b, nir_ssa_def *val, 2248bf215546Sopenharmony_ci const struct glsl_type *type) 2249bf215546Sopenharmony_ci{ 2250bf215546Sopenharmony_ci const unsigned num_components = glsl_get_vector_elements(type); 2251bf215546Sopenharmony_ci const unsigned bit_size = glsl_get_bit_size(type); 2252bf215546Sopenharmony_ci 2253bf215546Sopenharmony_ci /* First, zero-pad to ensure that the value is big enough that when we 2254bf215546Sopenharmony_ci * bit-cast it, we don't loose anything. 2255bf215546Sopenharmony_ci */ 2256bf215546Sopenharmony_ci if (val->bit_size < bit_size) { 2257bf215546Sopenharmony_ci const unsigned src_num_components_needed = 2258bf215546Sopenharmony_ci vtn_align_u32(val->num_components, bit_size / val->bit_size); 2259bf215546Sopenharmony_ci val = nir_shrink_zero_pad_vec(b, val, src_num_components_needed); 2260bf215546Sopenharmony_ci } 2261bf215546Sopenharmony_ci 2262bf215546Sopenharmony_ci val = nir_bitcast_vector(b, val, bit_size); 2263bf215546Sopenharmony_ci 2264bf215546Sopenharmony_ci return nir_shrink_zero_pad_vec(b, val, num_components); 2265bf215546Sopenharmony_ci} 2266bf215546Sopenharmony_ci 2267bf215546Sopenharmony_cistatic bool 2268bf215546Sopenharmony_civtn_get_mem_operands(struct vtn_builder *b, const uint32_t *w, unsigned count, 2269bf215546Sopenharmony_ci unsigned *idx, SpvMemoryAccessMask *access, unsigned *alignment, 2270bf215546Sopenharmony_ci SpvScope *dest_scope, SpvScope *src_scope) 2271bf215546Sopenharmony_ci{ 2272bf215546Sopenharmony_ci *access = 0; 2273bf215546Sopenharmony_ci *alignment = 0; 2274bf215546Sopenharmony_ci if (*idx >= count) 2275bf215546Sopenharmony_ci return false; 2276bf215546Sopenharmony_ci 2277bf215546Sopenharmony_ci *access = w[(*idx)++]; 2278bf215546Sopenharmony_ci if (*access & SpvMemoryAccessAlignedMask) { 2279bf215546Sopenharmony_ci vtn_assert(*idx < count); 2280bf215546Sopenharmony_ci *alignment = w[(*idx)++]; 2281bf215546Sopenharmony_ci } 2282bf215546Sopenharmony_ci 2283bf215546Sopenharmony_ci if (*access & SpvMemoryAccessMakePointerAvailableMask) { 2284bf215546Sopenharmony_ci vtn_assert(*idx < count); 2285bf215546Sopenharmony_ci vtn_assert(dest_scope); 2286bf215546Sopenharmony_ci *dest_scope = vtn_constant_uint(b, w[(*idx)++]); 2287bf215546Sopenharmony_ci } 2288bf215546Sopenharmony_ci 2289bf215546Sopenharmony_ci if (*access & SpvMemoryAccessMakePointerVisibleMask) { 2290bf215546Sopenharmony_ci vtn_assert(*idx < count); 2291bf215546Sopenharmony_ci vtn_assert(src_scope); 2292bf215546Sopenharmony_ci *src_scope = vtn_constant_uint(b, w[(*idx)++]); 2293bf215546Sopenharmony_ci } 2294bf215546Sopenharmony_ci 2295bf215546Sopenharmony_ci return true; 2296bf215546Sopenharmony_ci} 2297bf215546Sopenharmony_ci 2298bf215546Sopenharmony_cistatic enum gl_access_qualifier 2299bf215546Sopenharmony_cispv_access_to_gl_access(SpvMemoryAccessMask access) 2300bf215546Sopenharmony_ci{ 2301bf215546Sopenharmony_ci unsigned result = 0; 2302bf215546Sopenharmony_ci 2303bf215546Sopenharmony_ci if (access & SpvMemoryAccessVolatileMask) 2304bf215546Sopenharmony_ci result |= ACCESS_VOLATILE; 2305bf215546Sopenharmony_ci if (access & SpvMemoryAccessNontemporalMask) 2306bf215546Sopenharmony_ci result |= ACCESS_STREAM_CACHE_POLICY; 2307bf215546Sopenharmony_ci 2308bf215546Sopenharmony_ci return result; 2309bf215546Sopenharmony_ci} 2310bf215546Sopenharmony_ci 2311bf215546Sopenharmony_ci 2312bf215546Sopenharmony_ciSpvMemorySemanticsMask 2313bf215546Sopenharmony_civtn_mode_to_memory_semantics(enum vtn_variable_mode mode) 2314bf215546Sopenharmony_ci{ 2315bf215546Sopenharmony_ci switch (mode) { 2316bf215546Sopenharmony_ci case vtn_variable_mode_ssbo: 2317bf215546Sopenharmony_ci case vtn_variable_mode_phys_ssbo: 2318bf215546Sopenharmony_ci return SpvMemorySemanticsUniformMemoryMask; 2319bf215546Sopenharmony_ci case vtn_variable_mode_workgroup: 2320bf215546Sopenharmony_ci return SpvMemorySemanticsWorkgroupMemoryMask; 2321bf215546Sopenharmony_ci case vtn_variable_mode_cross_workgroup: 2322bf215546Sopenharmony_ci return SpvMemorySemanticsCrossWorkgroupMemoryMask; 2323bf215546Sopenharmony_ci case vtn_variable_mode_atomic_counter: 2324bf215546Sopenharmony_ci return SpvMemorySemanticsAtomicCounterMemoryMask; 2325bf215546Sopenharmony_ci case vtn_variable_mode_image: 2326bf215546Sopenharmony_ci return SpvMemorySemanticsImageMemoryMask; 2327bf215546Sopenharmony_ci case vtn_variable_mode_output: 2328bf215546Sopenharmony_ci return SpvMemorySemanticsOutputMemoryMask; 2329bf215546Sopenharmony_ci default: 2330bf215546Sopenharmony_ci return SpvMemorySemanticsMaskNone; 2331bf215546Sopenharmony_ci } 2332bf215546Sopenharmony_ci} 2333bf215546Sopenharmony_ci 2334bf215546Sopenharmony_cistatic void 2335bf215546Sopenharmony_civtn_emit_make_visible_barrier(struct vtn_builder *b, SpvMemoryAccessMask access, 2336bf215546Sopenharmony_ci SpvScope scope, enum vtn_variable_mode mode) 2337bf215546Sopenharmony_ci{ 2338bf215546Sopenharmony_ci if (!(access & SpvMemoryAccessMakePointerVisibleMask)) 2339bf215546Sopenharmony_ci return; 2340bf215546Sopenharmony_ci 2341bf215546Sopenharmony_ci vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeVisibleMask | 2342bf215546Sopenharmony_ci SpvMemorySemanticsAcquireMask | 2343bf215546Sopenharmony_ci vtn_mode_to_memory_semantics(mode)); 2344bf215546Sopenharmony_ci} 2345bf215546Sopenharmony_ci 2346bf215546Sopenharmony_cistatic void 2347bf215546Sopenharmony_civtn_emit_make_available_barrier(struct vtn_builder *b, SpvMemoryAccessMask access, 2348bf215546Sopenharmony_ci SpvScope scope, enum vtn_variable_mode mode) 2349bf215546Sopenharmony_ci{ 2350bf215546Sopenharmony_ci if (!(access & SpvMemoryAccessMakePointerAvailableMask)) 2351bf215546Sopenharmony_ci return; 2352bf215546Sopenharmony_ci 2353bf215546Sopenharmony_ci vtn_emit_memory_barrier(b, scope, SpvMemorySemanticsMakeAvailableMask | 2354bf215546Sopenharmony_ci SpvMemorySemanticsReleaseMask | 2355bf215546Sopenharmony_ci vtn_mode_to_memory_semantics(mode)); 2356bf215546Sopenharmony_ci} 2357bf215546Sopenharmony_ci 2358bf215546Sopenharmony_cistatic void 2359bf215546Sopenharmony_ciptr_nonuniform_workaround_cb(struct vtn_builder *b, struct vtn_value *val, 2360bf215546Sopenharmony_ci int member, const struct vtn_decoration *dec, void *void_ptr) 2361bf215546Sopenharmony_ci{ 2362bf215546Sopenharmony_ci enum gl_access_qualifier *access = void_ptr; 2363bf215546Sopenharmony_ci 2364bf215546Sopenharmony_ci switch (dec->decoration) { 2365bf215546Sopenharmony_ci case SpvDecorationNonUniformEXT: 2366bf215546Sopenharmony_ci *access |= ACCESS_NON_UNIFORM; 2367bf215546Sopenharmony_ci break; 2368bf215546Sopenharmony_ci 2369bf215546Sopenharmony_ci default: 2370bf215546Sopenharmony_ci break; 2371bf215546Sopenharmony_ci } 2372bf215546Sopenharmony_ci} 2373bf215546Sopenharmony_ci 2374bf215546Sopenharmony_civoid 2375bf215546Sopenharmony_civtn_handle_variables(struct vtn_builder *b, SpvOp opcode, 2376bf215546Sopenharmony_ci const uint32_t *w, unsigned count) 2377bf215546Sopenharmony_ci{ 2378bf215546Sopenharmony_ci switch (opcode) { 2379bf215546Sopenharmony_ci case SpvOpUndef: { 2380bf215546Sopenharmony_ci struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef); 2381bf215546Sopenharmony_ci val->type = vtn_get_type(b, w[1]); 2382bf215546Sopenharmony_ci val->is_undef_constant = true; 2383bf215546Sopenharmony_ci break; 2384bf215546Sopenharmony_ci } 2385bf215546Sopenharmony_ci 2386bf215546Sopenharmony_ci case SpvOpVariable: { 2387bf215546Sopenharmony_ci struct vtn_type *ptr_type = vtn_get_type(b, w[1]); 2388bf215546Sopenharmony_ci 2389bf215546Sopenharmony_ci SpvStorageClass storage_class = w[3]; 2390bf215546Sopenharmony_ci 2391bf215546Sopenharmony_ci const bool is_global = storage_class != SpvStorageClassFunction; 2392bf215546Sopenharmony_ci const bool is_io = storage_class == SpvStorageClassInput || 2393bf215546Sopenharmony_ci storage_class == SpvStorageClassOutput; 2394bf215546Sopenharmony_ci 2395bf215546Sopenharmony_ci /* Skip global variables that are not used by the entrypoint. Before 2396bf215546Sopenharmony_ci * SPIR-V 1.4 the interface is only used for I/O variables, so extra 2397bf215546Sopenharmony_ci * variables will still need to be removed later. 2398bf215546Sopenharmony_ci */ 2399bf215546Sopenharmony_ci if (!b->options->create_library && 2400bf215546Sopenharmony_ci (is_io || (b->version >= 0x10400 && is_global))) { 2401bf215546Sopenharmony_ci if (!bsearch(&w[2], b->interface_ids, b->interface_ids_count, 4, cmp_uint32_t)) 2402bf215546Sopenharmony_ci break; 2403bf215546Sopenharmony_ci } 2404bf215546Sopenharmony_ci 2405bf215546Sopenharmony_ci struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); 2406bf215546Sopenharmony_ci struct vtn_value *initializer = count > 4 ? vtn_untyped_value(b, w[4]) : NULL; 2407bf215546Sopenharmony_ci 2408bf215546Sopenharmony_ci vtn_create_variable(b, val, ptr_type, storage_class, initializer); 2409bf215546Sopenharmony_ci 2410bf215546Sopenharmony_ci break; 2411bf215546Sopenharmony_ci } 2412bf215546Sopenharmony_ci 2413bf215546Sopenharmony_ci case SpvOpConstantSampler: { 2414bf215546Sopenharmony_ci /* Synthesize a pointer-to-sampler type, create a variable of that type, 2415bf215546Sopenharmony_ci * and give the variable a constant initializer with the sampler params */ 2416bf215546Sopenharmony_ci struct vtn_type *sampler_type = vtn_value(b, w[1], vtn_value_type_type)->type; 2417bf215546Sopenharmony_ci struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); 2418bf215546Sopenharmony_ci 2419bf215546Sopenharmony_ci struct vtn_type *ptr_type = rzalloc(b, struct vtn_type); 2420bf215546Sopenharmony_ci ptr_type = rzalloc(b, struct vtn_type); 2421bf215546Sopenharmony_ci ptr_type->base_type = vtn_base_type_pointer; 2422bf215546Sopenharmony_ci ptr_type->deref = sampler_type; 2423bf215546Sopenharmony_ci ptr_type->storage_class = SpvStorageClassUniform; 2424bf215546Sopenharmony_ci 2425bf215546Sopenharmony_ci ptr_type->type = nir_address_format_to_glsl_type( 2426bf215546Sopenharmony_ci vtn_mode_to_address_format(b, vtn_variable_mode_function)); 2427bf215546Sopenharmony_ci 2428bf215546Sopenharmony_ci vtn_create_variable(b, val, ptr_type, ptr_type->storage_class, NULL); 2429bf215546Sopenharmony_ci 2430bf215546Sopenharmony_ci nir_variable *nir_var = val->pointer->var->var; 2431bf215546Sopenharmony_ci nir_var->data.sampler.is_inline_sampler = true; 2432bf215546Sopenharmony_ci nir_var->data.sampler.addressing_mode = w[3]; 2433bf215546Sopenharmony_ci nir_var->data.sampler.normalized_coordinates = w[4]; 2434bf215546Sopenharmony_ci nir_var->data.sampler.filter_mode = w[5]; 2435bf215546Sopenharmony_ci 2436bf215546Sopenharmony_ci break; 2437bf215546Sopenharmony_ci } 2438bf215546Sopenharmony_ci 2439bf215546Sopenharmony_ci case SpvOpAccessChain: 2440bf215546Sopenharmony_ci case SpvOpPtrAccessChain: 2441bf215546Sopenharmony_ci case SpvOpInBoundsAccessChain: 2442bf215546Sopenharmony_ci case SpvOpInBoundsPtrAccessChain: { 2443bf215546Sopenharmony_ci struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4); 2444bf215546Sopenharmony_ci enum gl_access_qualifier access = 0; 2445bf215546Sopenharmony_ci chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain); 2446bf215546Sopenharmony_ci 2447bf215546Sopenharmony_ci unsigned idx = 0; 2448bf215546Sopenharmony_ci for (int i = 4; i < count; i++) { 2449bf215546Sopenharmony_ci struct vtn_value *link_val = vtn_untyped_value(b, w[i]); 2450bf215546Sopenharmony_ci if (link_val->value_type == vtn_value_type_constant) { 2451bf215546Sopenharmony_ci chain->link[idx].mode = vtn_access_mode_literal; 2452bf215546Sopenharmony_ci chain->link[idx].id = vtn_constant_int(b, w[i]); 2453bf215546Sopenharmony_ci } else { 2454bf215546Sopenharmony_ci chain->link[idx].mode = vtn_access_mode_id; 2455bf215546Sopenharmony_ci chain->link[idx].id = w[i]; 2456bf215546Sopenharmony_ci } 2457bf215546Sopenharmony_ci 2458bf215546Sopenharmony_ci /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */ 2459bf215546Sopenharmony_ci vtn_foreach_decoration(b, link_val, ptr_nonuniform_workaround_cb, &access); 2460bf215546Sopenharmony_ci 2461bf215546Sopenharmony_ci idx++; 2462bf215546Sopenharmony_ci } 2463bf215546Sopenharmony_ci 2464bf215546Sopenharmony_ci struct vtn_type *ptr_type = vtn_get_type(b, w[1]); 2465bf215546Sopenharmony_ci 2466bf215546Sopenharmony_ci struct vtn_pointer *base = vtn_pointer(b, w[3]); 2467bf215546Sopenharmony_ci 2468bf215546Sopenharmony_ci chain->in_bounds = (opcode == SpvOpInBoundsAccessChain || opcode == SpvOpInBoundsPtrAccessChain); 2469bf215546Sopenharmony_ci 2470bf215546Sopenharmony_ci /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */ 2471bf215546Sopenharmony_ci access |= base->access & ACCESS_NON_UNIFORM; 2472bf215546Sopenharmony_ci 2473bf215546Sopenharmony_ci struct vtn_pointer *ptr = vtn_pointer_dereference(b, base, chain); 2474bf215546Sopenharmony_ci ptr->ptr_type = ptr_type; 2475bf215546Sopenharmony_ci ptr->access |= access; 2476bf215546Sopenharmony_ci vtn_push_pointer(b, w[2], ptr); 2477bf215546Sopenharmony_ci break; 2478bf215546Sopenharmony_ci } 2479bf215546Sopenharmony_ci 2480bf215546Sopenharmony_ci case SpvOpCopyMemory: { 2481bf215546Sopenharmony_ci struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); 2482bf215546Sopenharmony_ci struct vtn_value *src_val = vtn_pointer_value(b, w[2]); 2483bf215546Sopenharmony_ci struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); 2484bf215546Sopenharmony_ci struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); 2485bf215546Sopenharmony_ci 2486bf215546Sopenharmony_ci vtn_assert_types_equal(b, opcode, dest_val->type->deref, 2487bf215546Sopenharmony_ci src_val->type->deref); 2488bf215546Sopenharmony_ci 2489bf215546Sopenharmony_ci unsigned idx = 3, dest_alignment, src_alignment; 2490bf215546Sopenharmony_ci SpvMemoryAccessMask dest_access, src_access; 2491bf215546Sopenharmony_ci SpvScope dest_scope, src_scope; 2492bf215546Sopenharmony_ci vtn_get_mem_operands(b, w, count, &idx, &dest_access, &dest_alignment, 2493bf215546Sopenharmony_ci &dest_scope, &src_scope); 2494bf215546Sopenharmony_ci if (!vtn_get_mem_operands(b, w, count, &idx, &src_access, &src_alignment, 2495bf215546Sopenharmony_ci NULL, &src_scope)) { 2496bf215546Sopenharmony_ci src_alignment = dest_alignment; 2497bf215546Sopenharmony_ci src_access = dest_access; 2498bf215546Sopenharmony_ci } 2499bf215546Sopenharmony_ci src = vtn_align_pointer(b, src, src_alignment); 2500bf215546Sopenharmony_ci dest = vtn_align_pointer(b, dest, dest_alignment); 2501bf215546Sopenharmony_ci 2502bf215546Sopenharmony_ci vtn_emit_make_visible_barrier(b, src_access, src_scope, src->mode); 2503bf215546Sopenharmony_ci 2504bf215546Sopenharmony_ci vtn_variable_copy(b, dest, src, 2505bf215546Sopenharmony_ci spv_access_to_gl_access(dest_access), 2506bf215546Sopenharmony_ci spv_access_to_gl_access(src_access)); 2507bf215546Sopenharmony_ci 2508bf215546Sopenharmony_ci vtn_emit_make_available_barrier(b, dest_access, dest_scope, dest->mode); 2509bf215546Sopenharmony_ci break; 2510bf215546Sopenharmony_ci } 2511bf215546Sopenharmony_ci 2512bf215546Sopenharmony_ci case SpvOpCopyMemorySized: { 2513bf215546Sopenharmony_ci struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); 2514bf215546Sopenharmony_ci struct vtn_value *src_val = vtn_pointer_value(b, w[2]); 2515bf215546Sopenharmony_ci nir_ssa_def *size = vtn_get_nir_ssa(b, w[3]); 2516bf215546Sopenharmony_ci struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); 2517bf215546Sopenharmony_ci struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); 2518bf215546Sopenharmony_ci 2519bf215546Sopenharmony_ci unsigned idx = 4, dest_alignment, src_alignment; 2520bf215546Sopenharmony_ci SpvMemoryAccessMask dest_access, src_access; 2521bf215546Sopenharmony_ci SpvScope dest_scope, src_scope; 2522bf215546Sopenharmony_ci vtn_get_mem_operands(b, w, count, &idx, &dest_access, &dest_alignment, 2523bf215546Sopenharmony_ci &dest_scope, &src_scope); 2524bf215546Sopenharmony_ci if (!vtn_get_mem_operands(b, w, count, &idx, &src_access, &src_alignment, 2525bf215546Sopenharmony_ci NULL, &src_scope)) { 2526bf215546Sopenharmony_ci src_alignment = dest_alignment; 2527bf215546Sopenharmony_ci src_access = dest_access; 2528bf215546Sopenharmony_ci } 2529bf215546Sopenharmony_ci src = vtn_align_pointer(b, src, src_alignment); 2530bf215546Sopenharmony_ci dest = vtn_align_pointer(b, dest, dest_alignment); 2531bf215546Sopenharmony_ci 2532bf215546Sopenharmony_ci vtn_emit_make_visible_barrier(b, src_access, src_scope, src->mode); 2533bf215546Sopenharmony_ci 2534bf215546Sopenharmony_ci nir_memcpy_deref_with_access(&b->nb, 2535bf215546Sopenharmony_ci vtn_pointer_to_deref(b, dest), 2536bf215546Sopenharmony_ci vtn_pointer_to_deref(b, src), 2537bf215546Sopenharmony_ci size, 2538bf215546Sopenharmony_ci spv_access_to_gl_access(dest_access), 2539bf215546Sopenharmony_ci spv_access_to_gl_access(src_access)); 2540bf215546Sopenharmony_ci 2541bf215546Sopenharmony_ci vtn_emit_make_available_barrier(b, dest_access, dest_scope, dest->mode); 2542bf215546Sopenharmony_ci break; 2543bf215546Sopenharmony_ci } 2544bf215546Sopenharmony_ci 2545bf215546Sopenharmony_ci case SpvOpLoad: { 2546bf215546Sopenharmony_ci struct vtn_type *res_type = vtn_get_type(b, w[1]); 2547bf215546Sopenharmony_ci struct vtn_value *src_val = vtn_value(b, w[3], vtn_value_type_pointer); 2548bf215546Sopenharmony_ci struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); 2549bf215546Sopenharmony_ci 2550bf215546Sopenharmony_ci vtn_assert_types_equal(b, opcode, res_type, src_val->type->deref); 2551bf215546Sopenharmony_ci 2552bf215546Sopenharmony_ci unsigned idx = 4, alignment; 2553bf215546Sopenharmony_ci SpvMemoryAccessMask access; 2554bf215546Sopenharmony_ci SpvScope scope; 2555bf215546Sopenharmony_ci vtn_get_mem_operands(b, w, count, &idx, &access, &alignment, NULL, &scope); 2556bf215546Sopenharmony_ci src = vtn_align_pointer(b, src, alignment); 2557bf215546Sopenharmony_ci 2558bf215546Sopenharmony_ci vtn_emit_make_visible_barrier(b, access, scope, src->mode); 2559bf215546Sopenharmony_ci 2560bf215546Sopenharmony_ci vtn_push_ssa_value(b, w[2], vtn_variable_load(b, src, spv_access_to_gl_access(access))); 2561bf215546Sopenharmony_ci break; 2562bf215546Sopenharmony_ci } 2563bf215546Sopenharmony_ci 2564bf215546Sopenharmony_ci case SpvOpStore: { 2565bf215546Sopenharmony_ci struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); 2566bf215546Sopenharmony_ci struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); 2567bf215546Sopenharmony_ci struct vtn_value *src_val = vtn_untyped_value(b, w[2]); 2568bf215546Sopenharmony_ci 2569bf215546Sopenharmony_ci /* OpStore requires us to actually have a storage type */ 2570bf215546Sopenharmony_ci vtn_fail_if(dest->type->type == NULL, 2571bf215546Sopenharmony_ci "Invalid destination type for OpStore"); 2572bf215546Sopenharmony_ci 2573bf215546Sopenharmony_ci if (glsl_get_base_type(dest->type->type) == GLSL_TYPE_BOOL && 2574bf215546Sopenharmony_ci glsl_get_base_type(src_val->type->type) == GLSL_TYPE_UINT) { 2575bf215546Sopenharmony_ci /* Early versions of GLSLang would use uint types for UBOs/SSBOs but 2576bf215546Sopenharmony_ci * would then store them to a local variable as bool. Work around 2577bf215546Sopenharmony_ci * the issue by doing an implicit conversion. 2578bf215546Sopenharmony_ci * 2579bf215546Sopenharmony_ci * https://github.com/KhronosGroup/glslang/issues/170 2580bf215546Sopenharmony_ci * https://bugs.freedesktop.org/show_bug.cgi?id=104424 2581bf215546Sopenharmony_ci */ 2582bf215546Sopenharmony_ci vtn_warn("OpStore of value of type OpTypeInt to a pointer to type " 2583bf215546Sopenharmony_ci "OpTypeBool. Doing an implicit conversion to work around " 2584bf215546Sopenharmony_ci "the problem."); 2585bf215546Sopenharmony_ci struct vtn_ssa_value *bool_ssa = 2586bf215546Sopenharmony_ci vtn_create_ssa_value(b, dest->type->type); 2587bf215546Sopenharmony_ci bool_ssa->def = nir_i2b(&b->nb, vtn_ssa_value(b, w[2])->def); 2588bf215546Sopenharmony_ci vtn_variable_store(b, bool_ssa, dest, 0); 2589bf215546Sopenharmony_ci break; 2590bf215546Sopenharmony_ci } 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci vtn_assert_types_equal(b, opcode, dest_val->type->deref, src_val->type); 2593bf215546Sopenharmony_ci 2594bf215546Sopenharmony_ci unsigned idx = 3, alignment; 2595bf215546Sopenharmony_ci SpvMemoryAccessMask access; 2596bf215546Sopenharmony_ci SpvScope scope; 2597bf215546Sopenharmony_ci vtn_get_mem_operands(b, w, count, &idx, &access, &alignment, &scope, NULL); 2598bf215546Sopenharmony_ci dest = vtn_align_pointer(b, dest, alignment); 2599bf215546Sopenharmony_ci 2600bf215546Sopenharmony_ci struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]); 2601bf215546Sopenharmony_ci vtn_variable_store(b, src, dest, spv_access_to_gl_access(access)); 2602bf215546Sopenharmony_ci 2603bf215546Sopenharmony_ci vtn_emit_make_available_barrier(b, access, scope, dest->mode); 2604bf215546Sopenharmony_ci break; 2605bf215546Sopenharmony_ci } 2606bf215546Sopenharmony_ci 2607bf215546Sopenharmony_ci case SpvOpArrayLength: { 2608bf215546Sopenharmony_ci struct vtn_pointer *ptr = vtn_pointer(b, w[3]); 2609bf215546Sopenharmony_ci const uint32_t field = w[4]; 2610bf215546Sopenharmony_ci 2611bf215546Sopenharmony_ci vtn_fail_if(ptr->type->base_type != vtn_base_type_struct, 2612bf215546Sopenharmony_ci "OpArrayLength must take a pointer to a structure type"); 2613bf215546Sopenharmony_ci vtn_fail_if(field != ptr->type->length - 1 || 2614bf215546Sopenharmony_ci ptr->type->members[field]->base_type != vtn_base_type_array, 2615bf215546Sopenharmony_ci "OpArrayLength must reference the last memeber of the " 2616bf215546Sopenharmony_ci "structure and that must be an array"); 2617bf215546Sopenharmony_ci 2618bf215546Sopenharmony_ci if (b->options->use_deref_buffer_array_length) { 2619bf215546Sopenharmony_ci struct vtn_access_chain chain = { 2620bf215546Sopenharmony_ci .length = 1, 2621bf215546Sopenharmony_ci .link = { 2622bf215546Sopenharmony_ci { .mode = vtn_access_mode_literal, .id = field }, 2623bf215546Sopenharmony_ci } 2624bf215546Sopenharmony_ci }; 2625bf215546Sopenharmony_ci struct vtn_pointer *array = vtn_pointer_dereference(b, ptr, &chain); 2626bf215546Sopenharmony_ci 2627bf215546Sopenharmony_ci nir_ssa_def *array_length = 2628bf215546Sopenharmony_ci nir_build_deref_buffer_array_length(&b->nb, 32, 2629bf215546Sopenharmony_ci vtn_pointer_to_ssa(b, array), 2630bf215546Sopenharmony_ci .access=ptr->access | ptr->type->access); 2631bf215546Sopenharmony_ci 2632bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], array_length); 2633bf215546Sopenharmony_ci } else { 2634bf215546Sopenharmony_ci const uint32_t offset = ptr->type->offsets[field]; 2635bf215546Sopenharmony_ci const uint32_t stride = ptr->type->members[field]->stride; 2636bf215546Sopenharmony_ci 2637bf215546Sopenharmony_ci if (!ptr->block_index) { 2638bf215546Sopenharmony_ci struct vtn_access_chain chain = { 2639bf215546Sopenharmony_ci .length = 0, 2640bf215546Sopenharmony_ci }; 2641bf215546Sopenharmony_ci ptr = vtn_pointer_dereference(b, ptr, &chain); 2642bf215546Sopenharmony_ci vtn_assert(ptr->block_index); 2643bf215546Sopenharmony_ci } 2644bf215546Sopenharmony_ci 2645bf215546Sopenharmony_ci nir_ssa_def *buf_size = nir_get_ssbo_size(&b->nb, ptr->block_index, 2646bf215546Sopenharmony_ci .access=ptr->access | ptr->type->access); 2647bf215546Sopenharmony_ci 2648bf215546Sopenharmony_ci /* array_length = max(buffer_size - offset, 0) / stride */ 2649bf215546Sopenharmony_ci nir_ssa_def *array_length = 2650bf215546Sopenharmony_ci nir_udiv_imm(&b->nb, 2651bf215546Sopenharmony_ci nir_usub_sat(&b->nb, 2652bf215546Sopenharmony_ci buf_size, 2653bf215546Sopenharmony_ci nir_imm_int(&b->nb, offset)), 2654bf215546Sopenharmony_ci stride); 2655bf215546Sopenharmony_ci 2656bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], array_length); 2657bf215546Sopenharmony_ci } 2658bf215546Sopenharmony_ci break; 2659bf215546Sopenharmony_ci } 2660bf215546Sopenharmony_ci 2661bf215546Sopenharmony_ci case SpvOpConvertPtrToU: { 2662bf215546Sopenharmony_ci struct vtn_type *u_type = vtn_get_type(b, w[1]); 2663bf215546Sopenharmony_ci struct vtn_type *ptr_type = vtn_get_value_type(b, w[3]); 2664bf215546Sopenharmony_ci 2665bf215546Sopenharmony_ci vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer || 2666bf215546Sopenharmony_ci ptr_type->type == NULL, 2667bf215546Sopenharmony_ci "OpConvertPtrToU can only be used on physical pointers"); 2668bf215546Sopenharmony_ci 2669bf215546Sopenharmony_ci vtn_fail_if(u_type->base_type != vtn_base_type_vector && 2670bf215546Sopenharmony_ci u_type->base_type != vtn_base_type_scalar, 2671bf215546Sopenharmony_ci "OpConvertPtrToU can only be used to cast to a vector or " 2672bf215546Sopenharmony_ci "scalar type"); 2673bf215546Sopenharmony_ci 2674bf215546Sopenharmony_ci /* The pointer will be converted to an SSA value automatically */ 2675bf215546Sopenharmony_ci nir_ssa_def *ptr = vtn_get_nir_ssa(b, w[3]); 2676bf215546Sopenharmony_ci nir_ssa_def *u = nir_sloppy_bitcast(&b->nb, ptr, u_type->type); 2677bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], u); 2678bf215546Sopenharmony_ci break; 2679bf215546Sopenharmony_ci } 2680bf215546Sopenharmony_ci 2681bf215546Sopenharmony_ci case SpvOpConvertUToPtr: { 2682bf215546Sopenharmony_ci struct vtn_type *ptr_type = vtn_get_type(b, w[1]); 2683bf215546Sopenharmony_ci struct vtn_type *u_type = vtn_get_value_type(b, w[3]); 2684bf215546Sopenharmony_ci 2685bf215546Sopenharmony_ci vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer || 2686bf215546Sopenharmony_ci ptr_type->type == NULL, 2687bf215546Sopenharmony_ci "OpConvertUToPtr can only be used on physical pointers"); 2688bf215546Sopenharmony_ci 2689bf215546Sopenharmony_ci vtn_fail_if(u_type->base_type != vtn_base_type_vector && 2690bf215546Sopenharmony_ci u_type->base_type != vtn_base_type_scalar, 2691bf215546Sopenharmony_ci "OpConvertUToPtr can only be used to cast from a vector or " 2692bf215546Sopenharmony_ci "scalar type"); 2693bf215546Sopenharmony_ci 2694bf215546Sopenharmony_ci nir_ssa_def *u = vtn_get_nir_ssa(b, w[3]); 2695bf215546Sopenharmony_ci nir_ssa_def *ptr = nir_sloppy_bitcast(&b->nb, u, ptr_type->type); 2696bf215546Sopenharmony_ci vtn_push_pointer(b, w[2], vtn_pointer_from_ssa(b, ptr, ptr_type)); 2697bf215546Sopenharmony_ci break; 2698bf215546Sopenharmony_ci } 2699bf215546Sopenharmony_ci 2700bf215546Sopenharmony_ci case SpvOpGenericCastToPtrExplicit: { 2701bf215546Sopenharmony_ci struct vtn_type *dst_type = vtn_get_type(b, w[1]); 2702bf215546Sopenharmony_ci struct vtn_type *src_type = vtn_get_value_type(b, w[3]); 2703bf215546Sopenharmony_ci SpvStorageClass storage_class = w[4]; 2704bf215546Sopenharmony_ci 2705bf215546Sopenharmony_ci vtn_fail_if(dst_type->base_type != vtn_base_type_pointer || 2706bf215546Sopenharmony_ci dst_type->storage_class != storage_class, 2707bf215546Sopenharmony_ci "Result type of an SpvOpGenericCastToPtrExplicit must be " 2708bf215546Sopenharmony_ci "an OpTypePointer. Its Storage Class must match the " 2709bf215546Sopenharmony_ci "storage class specified in the instruction"); 2710bf215546Sopenharmony_ci 2711bf215546Sopenharmony_ci vtn_fail_if(src_type->base_type != vtn_base_type_pointer || 2712bf215546Sopenharmony_ci src_type->deref->id != dst_type->deref->id, 2713bf215546Sopenharmony_ci "Source pointer of an SpvOpGenericCastToPtrExplicit must " 2714bf215546Sopenharmony_ci "have a type of OpTypePointer whose Type is the same as " 2715bf215546Sopenharmony_ci "the Type of Result Type"); 2716bf215546Sopenharmony_ci 2717bf215546Sopenharmony_ci vtn_fail_if(src_type->storage_class != SpvStorageClassGeneric, 2718bf215546Sopenharmony_ci "Source pointer of an SpvOpGenericCastToPtrExplicit must " 2719bf215546Sopenharmony_ci "point to the Generic Storage Class."); 2720bf215546Sopenharmony_ci 2721bf215546Sopenharmony_ci vtn_fail_if(storage_class != SpvStorageClassWorkgroup && 2722bf215546Sopenharmony_ci storage_class != SpvStorageClassCrossWorkgroup && 2723bf215546Sopenharmony_ci storage_class != SpvStorageClassFunction, 2724bf215546Sopenharmony_ci "Storage must be one of the following literal values from " 2725bf215546Sopenharmony_ci "Storage Class: Workgroup, CrossWorkgroup, or Function."); 2726bf215546Sopenharmony_ci 2727bf215546Sopenharmony_ci nir_deref_instr *src_deref = vtn_nir_deref(b, w[3]); 2728bf215546Sopenharmony_ci 2729bf215546Sopenharmony_ci nir_variable_mode nir_mode; 2730bf215546Sopenharmony_ci enum vtn_variable_mode mode = 2731bf215546Sopenharmony_ci vtn_storage_class_to_mode(b, storage_class, dst_type->deref, &nir_mode); 2732bf215546Sopenharmony_ci nir_address_format addr_format = vtn_mode_to_address_format(b, mode); 2733bf215546Sopenharmony_ci 2734bf215546Sopenharmony_ci nir_ssa_def *null_value = 2735bf215546Sopenharmony_ci nir_build_imm(&b->nb, nir_address_format_num_components(addr_format), 2736bf215546Sopenharmony_ci nir_address_format_bit_size(addr_format), 2737bf215546Sopenharmony_ci nir_address_format_null_value(addr_format)); 2738bf215546Sopenharmony_ci 2739bf215546Sopenharmony_ci nir_ssa_def *valid = nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa, nir_mode); 2740bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], nir_bcsel(&b->nb, valid, 2741bf215546Sopenharmony_ci &src_deref->dest.ssa, 2742bf215546Sopenharmony_ci null_value)); 2743bf215546Sopenharmony_ci break; 2744bf215546Sopenharmony_ci } 2745bf215546Sopenharmony_ci 2746bf215546Sopenharmony_ci case SpvOpGenericPtrMemSemantics: { 2747bf215546Sopenharmony_ci struct vtn_type *dst_type = vtn_get_type(b, w[1]); 2748bf215546Sopenharmony_ci struct vtn_type *src_type = vtn_get_value_type(b, w[3]); 2749bf215546Sopenharmony_ci 2750bf215546Sopenharmony_ci vtn_fail_if(dst_type->base_type != vtn_base_type_scalar || 2751bf215546Sopenharmony_ci dst_type->type != glsl_uint_type(), 2752bf215546Sopenharmony_ci "Result type of an SpvOpGenericPtrMemSemantics must be " 2753bf215546Sopenharmony_ci "an OpTypeInt with 32-bit Width and 0 Signedness."); 2754bf215546Sopenharmony_ci 2755bf215546Sopenharmony_ci vtn_fail_if(src_type->base_type != vtn_base_type_pointer || 2756bf215546Sopenharmony_ci src_type->storage_class != SpvStorageClassGeneric, 2757bf215546Sopenharmony_ci "Source pointer of an SpvOpGenericPtrMemSemantics must " 2758bf215546Sopenharmony_ci "point to the Generic Storage Class"); 2759bf215546Sopenharmony_ci 2760bf215546Sopenharmony_ci nir_deref_instr *src_deref = vtn_nir_deref(b, w[3]); 2761bf215546Sopenharmony_ci 2762bf215546Sopenharmony_ci nir_ssa_def *global_bit = 2763bf215546Sopenharmony_ci nir_bcsel(&b->nb, nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa, 2764bf215546Sopenharmony_ci nir_var_mem_global), 2765bf215546Sopenharmony_ci nir_imm_int(&b->nb, SpvMemorySemanticsCrossWorkgroupMemoryMask), 2766bf215546Sopenharmony_ci nir_imm_int(&b->nb, 0)); 2767bf215546Sopenharmony_ci 2768bf215546Sopenharmony_ci nir_ssa_def *shared_bit = 2769bf215546Sopenharmony_ci nir_bcsel(&b->nb, nir_build_deref_mode_is(&b->nb, 1, &src_deref->dest.ssa, 2770bf215546Sopenharmony_ci nir_var_mem_shared), 2771bf215546Sopenharmony_ci nir_imm_int(&b->nb, SpvMemorySemanticsWorkgroupMemoryMask), 2772bf215546Sopenharmony_ci nir_imm_int(&b->nb, 0)); 2773bf215546Sopenharmony_ci 2774bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], nir_iand(&b->nb, global_bit, shared_bit)); 2775bf215546Sopenharmony_ci break; 2776bf215546Sopenharmony_ci } 2777bf215546Sopenharmony_ci 2778bf215546Sopenharmony_ci case SpvOpSubgroupBlockReadINTEL: { 2779bf215546Sopenharmony_ci struct vtn_type *res_type = vtn_get_type(b, w[1]); 2780bf215546Sopenharmony_ci nir_deref_instr *src = vtn_nir_deref(b, w[3]); 2781bf215546Sopenharmony_ci 2782bf215546Sopenharmony_ci nir_intrinsic_instr *load = 2783bf215546Sopenharmony_ci nir_intrinsic_instr_create(b->nb.shader, 2784bf215546Sopenharmony_ci nir_intrinsic_load_deref_block_intel); 2785bf215546Sopenharmony_ci load->src[0] = nir_src_for_ssa(&src->dest.ssa); 2786bf215546Sopenharmony_ci nir_ssa_dest_init_for_type(&load->instr, &load->dest, 2787bf215546Sopenharmony_ci res_type->type, NULL); 2788bf215546Sopenharmony_ci load->num_components = load->dest.ssa.num_components; 2789bf215546Sopenharmony_ci nir_builder_instr_insert(&b->nb, &load->instr); 2790bf215546Sopenharmony_ci 2791bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], &load->dest.ssa); 2792bf215546Sopenharmony_ci break; 2793bf215546Sopenharmony_ci } 2794bf215546Sopenharmony_ci 2795bf215546Sopenharmony_ci case SpvOpSubgroupBlockWriteINTEL: { 2796bf215546Sopenharmony_ci nir_deref_instr *dest = vtn_nir_deref(b, w[1]); 2797bf215546Sopenharmony_ci nir_ssa_def *data = vtn_ssa_value(b, w[2])->def; 2798bf215546Sopenharmony_ci 2799bf215546Sopenharmony_ci nir_intrinsic_instr *store = 2800bf215546Sopenharmony_ci nir_intrinsic_instr_create(b->nb.shader, 2801bf215546Sopenharmony_ci nir_intrinsic_store_deref_block_intel); 2802bf215546Sopenharmony_ci store->src[0] = nir_src_for_ssa(&dest->dest.ssa); 2803bf215546Sopenharmony_ci store->src[1] = nir_src_for_ssa(data); 2804bf215546Sopenharmony_ci store->num_components = data->num_components; 2805bf215546Sopenharmony_ci nir_builder_instr_insert(&b->nb, &store->instr); 2806bf215546Sopenharmony_ci break; 2807bf215546Sopenharmony_ci } 2808bf215546Sopenharmony_ci 2809bf215546Sopenharmony_ci case SpvOpConvertUToAccelerationStructureKHR: { 2810bf215546Sopenharmony_ci struct vtn_type *as_type = vtn_get_type(b, w[1]); 2811bf215546Sopenharmony_ci struct vtn_type *u_type = vtn_get_value_type(b, w[3]); 2812bf215546Sopenharmony_ci vtn_fail_if(!((u_type->base_type == vtn_base_type_vector && 2813bf215546Sopenharmony_ci u_type->type == glsl_vector_type(GLSL_TYPE_UINT, 2)) || 2814bf215546Sopenharmony_ci (u_type->base_type == vtn_base_type_scalar && 2815bf215546Sopenharmony_ci u_type->type == glsl_uint64_t_type())), 2816bf215546Sopenharmony_ci "OpConvertUToAccelerationStructure may only be used to " 2817bf215546Sopenharmony_ci "cast from a 64-bit scalar integer or a 2-component vector " 2818bf215546Sopenharmony_ci "of 32-bit integers"); 2819bf215546Sopenharmony_ci vtn_fail_if(as_type->base_type != vtn_base_type_accel_struct, 2820bf215546Sopenharmony_ci "The result type of an OpConvertUToAccelerationStructure " 2821bf215546Sopenharmony_ci "must be OpTypeAccelerationStructure"); 2822bf215546Sopenharmony_ci 2823bf215546Sopenharmony_ci nir_ssa_def *u = vtn_get_nir_ssa(b, w[3]); 2824bf215546Sopenharmony_ci vtn_push_nir_ssa(b, w[2], nir_sloppy_bitcast(&b->nb, u, as_type->type)); 2825bf215546Sopenharmony_ci break; 2826bf215546Sopenharmony_ci } 2827bf215546Sopenharmony_ci 2828bf215546Sopenharmony_ci default: 2829bf215546Sopenharmony_ci vtn_fail_with_opcode("Unhandled opcode", opcode); 2830bf215546Sopenharmony_ci } 2831bf215546Sopenharmony_ci} 2832