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