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