bb41e89a33df7cb2c0eb713e1d27eec5cb9f87c5
[mesa.git] / src / compiler / spirv / vtn_variables.c
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
31 static struct vtn_access_chain *
32 vtn_access_chain_extend(struct vtn_builder *b, struct vtn_access_chain *old,
33 unsigned new_ids)
34 {
35 struct vtn_access_chain *chain;
36
37 unsigned new_len = old->length + new_ids;
38 /* TODO: don't use rzalloc */
39 chain = rzalloc_size(b, sizeof(*chain) + new_len * sizeof(chain->link[0]));
40
41 chain->var = old->var;
42 chain->length = new_len;
43
44 for (unsigned i = 0; i < old->length; i++)
45 chain->link[i] = old->link[i];
46
47 return chain;
48 }
49
50 static nir_ssa_def *
51 vtn_access_link_as_ssa(struct vtn_builder *b, struct vtn_access_link link,
52 unsigned stride)
53 {
54 assert(stride > 0);
55 if (link.mode == vtn_access_mode_literal) {
56 return nir_imm_int(&b->nb, link.id * stride);
57 } else if (stride == 1) {
58 return vtn_ssa_value(b, link.id)->def;
59 } else {
60 return nir_imul(&b->nb, vtn_ssa_value(b, link.id)->def,
61 nir_imm_int(&b->nb, stride));
62 }
63 }
64
65 static struct vtn_type *
66 vtn_access_chain_tail_type(struct vtn_builder *b,
67 struct vtn_access_chain *chain)
68 {
69 struct vtn_type *type = chain->var->type;
70 for (unsigned i = 0; i < chain->length; i++) {
71 if (glsl_type_is_struct(type->type)) {
72 assert(chain->link[i].mode == vtn_access_mode_literal);
73 type = type->members[chain->link[i].id];
74 } else {
75 type = type->array_element;
76 }
77 }
78 return type;
79 }
80
81 /* Crawls a chain of array derefs and rewrites the types so that the
82 * lengths stay the same but the terminal type is the one given by
83 * tail_type. This is useful for split structures.
84 */
85 static void
86 rewrite_deref_types(nir_deref *deref, const struct glsl_type *type)
87 {
88 deref->type = type;
89 if (deref->child) {
90 assert(deref->child->deref_type == nir_deref_type_array);
91 assert(glsl_type_is_array(deref->type));
92 rewrite_deref_types(deref->child, glsl_get_array_element(type));
93 }
94 }
95
96 nir_deref_var *
97 vtn_access_chain_to_deref(struct vtn_builder *b, struct vtn_access_chain *chain)
98 {
99 /* Do on-the-fly copy propagation for samplers. */
100 if (chain->var->copy_prop_sampler)
101 return vtn_access_chain_to_deref(b, chain->var->copy_prop_sampler);
102
103 nir_deref_var *deref_var;
104 if (chain->var->var) {
105 deref_var = nir_deref_var_create(b, chain->var->var);
106 } else {
107 assert(chain->var->members);
108 /* Create the deref_var manually. It will get filled out later. */
109 deref_var = rzalloc(b, nir_deref_var);
110 deref_var->deref.deref_type = nir_deref_type_var;
111 }
112
113 struct vtn_type *deref_type = chain->var->type;
114 nir_deref *tail = &deref_var->deref;
115 nir_variable **members = chain->var->members;
116
117 for (unsigned i = 0; i < chain->length; i++) {
118 enum glsl_base_type base_type = glsl_get_base_type(deref_type->type);
119 switch (base_type) {
120 case GLSL_TYPE_UINT:
121 case GLSL_TYPE_INT:
122 case GLSL_TYPE_UINT64:
123 case GLSL_TYPE_INT64:
124 case GLSL_TYPE_FLOAT:
125 case GLSL_TYPE_DOUBLE:
126 case GLSL_TYPE_BOOL:
127 case GLSL_TYPE_ARRAY: {
128 deref_type = deref_type->array_element;
129
130 nir_deref_array *deref_arr = nir_deref_array_create(b);
131 deref_arr->deref.type = deref_type->type;
132
133 if (chain->link[i].mode == vtn_access_mode_literal) {
134 deref_arr->deref_array_type = nir_deref_array_type_direct;
135 deref_arr->base_offset = chain->link[i].id;
136 } else {
137 assert(chain->link[i].mode == vtn_access_mode_id);
138 deref_arr->deref_array_type = nir_deref_array_type_indirect;
139 deref_arr->base_offset = 0;
140 deref_arr->indirect =
141 nir_src_for_ssa(vtn_ssa_value(b, chain->link[i].id)->def);
142 }
143 tail->child = &deref_arr->deref;
144 tail = tail->child;
145 break;
146 }
147
148 case GLSL_TYPE_STRUCT: {
149 assert(chain->link[i].mode == vtn_access_mode_literal);
150 unsigned idx = chain->link[i].id;
151 deref_type = deref_type->members[idx];
152 if (members) {
153 /* This is a pre-split structure. */
154 deref_var->var = members[idx];
155 rewrite_deref_types(&deref_var->deref, members[idx]->type);
156 assert(tail->type == deref_type->type);
157 members = NULL;
158 } else {
159 nir_deref_struct *deref_struct = nir_deref_struct_create(b, idx);
160 deref_struct->deref.type = deref_type->type;
161 tail->child = &deref_struct->deref;
162 tail = tail->child;
163 }
164 break;
165 }
166 default:
167 unreachable("Invalid type for deref");
168 }
169 }
170
171 assert(members == NULL);
172 return deref_var;
173 }
174
175 static void
176 _vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_var *deref,
177 nir_deref *tail, struct vtn_ssa_value *inout)
178 {
179 /* The deref tail may contain a deref to select a component of a vector (in
180 * other words, it might not be an actual tail) so we have to save it away
181 * here since we overwrite it later.
182 */
183 nir_deref *old_child = tail->child;
184
185 if (glsl_type_is_vector_or_scalar(tail->type)) {
186 /* Terminate the deref chain in case there is one more link to pick
187 * off a component of the vector.
188 */
189 tail->child = NULL;
190
191 nir_intrinsic_op op = load ? nir_intrinsic_load_var :
192 nir_intrinsic_store_var;
193
194 nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
195 intrin->variables[0] = nir_deref_var_clone(deref, intrin);
196 intrin->num_components = glsl_get_vector_elements(tail->type);
197
198 if (load) {
199 nir_ssa_dest_init(&intrin->instr, &intrin->dest,
200 intrin->num_components,
201 glsl_get_bit_size(tail->type),
202 NULL);
203 inout->def = &intrin->dest.ssa;
204 } else {
205 nir_intrinsic_set_write_mask(intrin, (1 << intrin->num_components) - 1);
206 intrin->src[0] = nir_src_for_ssa(inout->def);
207 }
208
209 nir_builder_instr_insert(&b->nb, &intrin->instr);
210 } else if (glsl_get_base_type(tail->type) == GLSL_TYPE_ARRAY ||
211 glsl_type_is_matrix(tail->type)) {
212 unsigned elems = glsl_get_length(tail->type);
213 nir_deref_array *deref_arr = nir_deref_array_create(b);
214 deref_arr->deref_array_type = nir_deref_array_type_direct;
215 deref_arr->deref.type = glsl_get_array_element(tail->type);
216 tail->child = &deref_arr->deref;
217 for (unsigned i = 0; i < elems; i++) {
218 deref_arr->base_offset = i;
219 _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]);
220 }
221 } else {
222 assert(glsl_get_base_type(tail->type) == GLSL_TYPE_STRUCT);
223 unsigned elems = glsl_get_length(tail->type);
224 nir_deref_struct *deref_struct = nir_deref_struct_create(b, 0);
225 tail->child = &deref_struct->deref;
226 for (unsigned i = 0; i < elems; i++) {
227 deref_struct->index = i;
228 deref_struct->deref.type = glsl_get_struct_field(tail->type, i);
229 _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]);
230 }
231 }
232
233 tail->child = old_child;
234 }
235
236 nir_deref_var *
237 vtn_nir_deref(struct vtn_builder *b, uint32_t id)
238 {
239 struct vtn_access_chain *chain =
240 vtn_value(b, id, vtn_value_type_access_chain)->access_chain;
241
242 return vtn_access_chain_to_deref(b, chain);
243 }
244
245 /*
246 * Gets the NIR-level deref tail, which may have as a child an array deref
247 * selecting which component due to OpAccessChain supporting per-component
248 * indexing in SPIR-V.
249 */
250 static nir_deref *
251 get_deref_tail(nir_deref_var *deref)
252 {
253 nir_deref *cur = &deref->deref;
254 while (!glsl_type_is_vector_or_scalar(cur->type) && cur->child)
255 cur = cur->child;
256
257 return cur;
258 }
259
260 struct vtn_ssa_value *
261 vtn_local_load(struct vtn_builder *b, nir_deref_var *src)
262 {
263 nir_deref *src_tail = get_deref_tail(src);
264 struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type);
265 _vtn_local_load_store(b, true, src, src_tail, val);
266
267 if (src_tail->child) {
268 nir_deref_array *vec_deref = nir_deref_as_array(src_tail->child);
269 assert(vec_deref->deref.child == NULL);
270 val->type = vec_deref->deref.type;
271 if (vec_deref->deref_array_type == nir_deref_array_type_direct)
272 val->def = vtn_vector_extract(b, val->def, vec_deref->base_offset);
273 else
274 val->def = vtn_vector_extract_dynamic(b, val->def,
275 vec_deref->indirect.ssa);
276 }
277
278 return val;
279 }
280
281 void
282 vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
283 nir_deref_var *dest)
284 {
285 nir_deref *dest_tail = get_deref_tail(dest);
286
287 if (dest_tail->child) {
288 struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);
289 _vtn_local_load_store(b, true, dest, dest_tail, val);
290 nir_deref_array *deref = nir_deref_as_array(dest_tail->child);
291 assert(deref->deref.child == NULL);
292 if (deref->deref_array_type == nir_deref_array_type_direct)
293 val->def = vtn_vector_insert(b, val->def, src->def,
294 deref->base_offset);
295 else
296 val->def = vtn_vector_insert_dynamic(b, val->def, src->def,
297 deref->indirect.ssa);
298 _vtn_local_load_store(b, false, dest, dest_tail, val);
299 } else {
300 _vtn_local_load_store(b, false, dest, dest_tail, src);
301 }
302 }
303
304 static nir_ssa_def *
305 get_vulkan_resource_index(struct vtn_builder *b, struct vtn_access_chain *chain,
306 struct vtn_type **type, unsigned *chain_idx)
307 {
308 /* Push constants have no explicit binding */
309 if (chain->var->mode == vtn_variable_mode_push_constant) {
310 *chain_idx = 0;
311 *type = chain->var->type;
312 return NULL;
313 }
314
315 nir_ssa_def *array_index;
316 if (glsl_type_is_array(chain->var->type->type)) {
317 assert(chain->length > 0);
318 array_index = vtn_access_link_as_ssa(b, chain->link[0], 1);
319 *chain_idx = 1;
320 *type = chain->var->type->array_element;
321 } else {
322 array_index = nir_imm_int(&b->nb, 0);
323 *chain_idx = 0;
324 *type = chain->var->type;
325 }
326
327 nir_intrinsic_instr *instr =
328 nir_intrinsic_instr_create(b->nb.shader,
329 nir_intrinsic_vulkan_resource_index);
330 instr->src[0] = nir_src_for_ssa(array_index);
331 nir_intrinsic_set_desc_set(instr, chain->var->descriptor_set);
332 nir_intrinsic_set_binding(instr, chain->var->binding);
333
334 nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, NULL);
335 nir_builder_instr_insert(&b->nb, &instr->instr);
336
337 return &instr->dest.ssa;
338 }
339
340 nir_ssa_def *
341 vtn_access_chain_to_offset(struct vtn_builder *b,
342 struct vtn_access_chain *chain,
343 nir_ssa_def **index_out, struct vtn_type **type_out,
344 unsigned *end_idx_out, bool stop_at_matrix)
345 {
346 unsigned idx = 0;
347 struct vtn_type *type;
348 *index_out = get_vulkan_resource_index(b, chain, &type, &idx);
349
350 nir_ssa_def *offset = nir_imm_int(&b->nb, 0);
351 for (; idx < chain->length; idx++) {
352 enum glsl_base_type base_type = glsl_get_base_type(type->type);
353 switch (base_type) {
354 case GLSL_TYPE_UINT:
355 case GLSL_TYPE_INT:
356 case GLSL_TYPE_UINT64:
357 case GLSL_TYPE_INT64:
358 case GLSL_TYPE_FLOAT:
359 case GLSL_TYPE_DOUBLE:
360 case GLSL_TYPE_BOOL:
361 /* Some users may not want matrix or vector derefs */
362 if (stop_at_matrix)
363 goto end;
364 /* Fall through */
365
366 case GLSL_TYPE_ARRAY:
367 offset = nir_iadd(&b->nb, offset,
368 vtn_access_link_as_ssa(b, chain->link[idx],
369 type->stride));
370
371 type = type->array_element;
372 break;
373
374 case GLSL_TYPE_STRUCT: {
375 assert(chain->link[idx].mode == vtn_access_mode_literal);
376 unsigned member = chain->link[idx].id;
377 offset = nir_iadd(&b->nb, offset,
378 nir_imm_int(&b->nb, type->offsets[member]));
379 type = type->members[member];
380 break;
381 }
382
383 default:
384 unreachable("Invalid type for deref");
385 }
386 }
387
388 end:
389 *type_out = type;
390 if (end_idx_out)
391 *end_idx_out = idx;
392
393 return offset;
394 }
395
396 /* Tries to compute the size of an interface block based on the strides and
397 * offsets that are provided to us in the SPIR-V source.
398 */
399 static unsigned
400 vtn_type_block_size(struct vtn_type *type)
401 {
402 enum glsl_base_type base_type = glsl_get_base_type(type->type);
403 switch (base_type) {
404 case GLSL_TYPE_UINT:
405 case GLSL_TYPE_INT:
406 case GLSL_TYPE_UINT64:
407 case GLSL_TYPE_INT64:
408 case GLSL_TYPE_FLOAT:
409 case GLSL_TYPE_BOOL:
410 case GLSL_TYPE_DOUBLE: {
411 unsigned cols = type->row_major ? glsl_get_vector_elements(type->type) :
412 glsl_get_matrix_columns(type->type);
413 if (cols > 1) {
414 assert(type->stride > 0);
415 return type->stride * cols;
416 } else if (base_type == GLSL_TYPE_DOUBLE ||
417 base_type == GLSL_TYPE_UINT64 ||
418 base_type == GLSL_TYPE_INT64) {
419 return glsl_get_vector_elements(type->type) * 8;
420 } else {
421 return glsl_get_vector_elements(type->type) * 4;
422 }
423 }
424
425 case GLSL_TYPE_STRUCT:
426 case GLSL_TYPE_INTERFACE: {
427 unsigned size = 0;
428 unsigned num_fields = glsl_get_length(type->type);
429 for (unsigned f = 0; f < num_fields; f++) {
430 unsigned field_end = type->offsets[f] +
431 vtn_type_block_size(type->members[f]);
432 size = MAX2(size, field_end);
433 }
434 return size;
435 }
436
437 case GLSL_TYPE_ARRAY:
438 assert(type->stride > 0);
439 assert(glsl_get_length(type->type) > 0);
440 return type->stride * glsl_get_length(type->type);
441
442 default:
443 assert(!"Invalid block type");
444 return 0;
445 }
446 }
447
448 static void
449 vtn_access_chain_get_offset_size(struct vtn_access_chain *chain,
450 unsigned *access_offset,
451 unsigned *access_size)
452 {
453 /* Only valid for push constants accesses now. */
454 assert(chain->var->mode == vtn_variable_mode_push_constant);
455
456 struct vtn_type *type = chain->var->type;
457
458 *access_offset = 0;
459
460 for (unsigned i = 0; i < chain->length; i++) {
461 if (chain->link[i].mode != vtn_access_mode_literal)
462 break;
463
464 if (glsl_type_is_struct(type->type)) {
465 *access_offset += type->offsets[chain->link[i].id];
466 type = type->members[chain->link[i].id];
467 } else {
468 *access_offset += type->stride * chain->link[i].id;
469 type = type->array_element;
470 }
471 }
472
473 *access_size = vtn_type_block_size(type);
474 }
475
476 static void
477 _vtn_load_store_tail(struct vtn_builder *b, nir_intrinsic_op op, bool load,
478 nir_ssa_def *index, nir_ssa_def *offset,
479 unsigned access_offset, unsigned access_size,
480 struct vtn_ssa_value **inout, const struct glsl_type *type)
481 {
482 nir_intrinsic_instr *instr = nir_intrinsic_instr_create(b->nb.shader, op);
483 instr->num_components = glsl_get_vector_elements(type);
484
485 int src = 0;
486 if (!load) {
487 nir_intrinsic_set_write_mask(instr, (1 << instr->num_components) - 1);
488 instr->src[src++] = nir_src_for_ssa((*inout)->def);
489 }
490
491 if (op == nir_intrinsic_load_push_constant) {
492 assert(access_offset % 4 == 0);
493
494 nir_intrinsic_set_base(instr, access_offset);
495 nir_intrinsic_set_range(instr, access_size);
496 }
497
498 if (index)
499 instr->src[src++] = nir_src_for_ssa(index);
500
501 if (op == nir_intrinsic_load_push_constant) {
502 /* We need to subtract the offset from where the intrinsic will load the
503 * data. */
504 instr->src[src++] =
505 nir_src_for_ssa(nir_isub(&b->nb, offset,
506 nir_imm_int(&b->nb, access_offset)));
507 } else {
508 instr->src[src++] = nir_src_for_ssa(offset);
509 }
510
511 if (load) {
512 nir_ssa_dest_init(&instr->instr, &instr->dest,
513 instr->num_components,
514 glsl_get_bit_size(type), NULL);
515 (*inout)->def = &instr->dest.ssa;
516 }
517
518 nir_builder_instr_insert(&b->nb, &instr->instr);
519
520 if (load && glsl_get_base_type(type) == GLSL_TYPE_BOOL)
521 (*inout)->def = nir_ine(&b->nb, (*inout)->def, nir_imm_int(&b->nb, 0));
522 }
523
524 static void
525 _vtn_block_load_store(struct vtn_builder *b, nir_intrinsic_op op, bool load,
526 nir_ssa_def *index, nir_ssa_def *offset,
527 unsigned access_offset, unsigned access_size,
528 struct vtn_access_chain *chain, unsigned chain_idx,
529 struct vtn_type *type, struct vtn_ssa_value **inout)
530 {
531 if (chain && chain_idx >= chain->length)
532 chain = NULL;
533
534 if (load && chain == NULL && *inout == NULL)
535 *inout = vtn_create_ssa_value(b, type->type);
536
537 enum glsl_base_type base_type = glsl_get_base_type(type->type);
538 switch (base_type) {
539 case GLSL_TYPE_UINT:
540 case GLSL_TYPE_INT:
541 case GLSL_TYPE_UINT64:
542 case GLSL_TYPE_INT64:
543 case GLSL_TYPE_FLOAT:
544 case GLSL_TYPE_DOUBLE:
545 case GLSL_TYPE_BOOL:
546 /* This is where things get interesting. At this point, we've hit
547 * a vector, a scalar, or a matrix.
548 */
549 if (glsl_type_is_matrix(type->type)) {
550 if (chain == NULL) {
551 /* Loading the whole matrix */
552 struct vtn_ssa_value *transpose;
553 unsigned num_ops, vec_width;
554 if (type->row_major) {
555 num_ops = glsl_get_vector_elements(type->type);
556 vec_width = glsl_get_matrix_columns(type->type);
557 if (load) {
558 const struct glsl_type *transpose_type =
559 glsl_matrix_type(base_type, vec_width, num_ops);
560 *inout = vtn_create_ssa_value(b, transpose_type);
561 } else {
562 transpose = vtn_ssa_transpose(b, *inout);
563 inout = &transpose;
564 }
565 } else {
566 num_ops = glsl_get_matrix_columns(type->type);
567 vec_width = glsl_get_vector_elements(type->type);
568 }
569
570 for (unsigned i = 0; i < num_ops; i++) {
571 nir_ssa_def *elem_offset =
572 nir_iadd(&b->nb, offset,
573 nir_imm_int(&b->nb, i * type->stride));
574 _vtn_load_store_tail(b, op, load, index, elem_offset,
575 access_offset, access_size,
576 &(*inout)->elems[i],
577 glsl_vector_type(base_type, vec_width));
578 }
579
580 if (load && type->row_major)
581 *inout = vtn_ssa_transpose(b, *inout);
582 } else if (type->row_major) {
583 /* Row-major but with an access chiain. */
584 nir_ssa_def *col_offset =
585 vtn_access_link_as_ssa(b, chain->link[chain_idx],
586 type->array_element->stride);
587 offset = nir_iadd(&b->nb, offset, col_offset);
588
589 if (chain_idx + 1 < chain->length) {
590 /* Picking off a single element */
591 nir_ssa_def *row_offset =
592 vtn_access_link_as_ssa(b, chain->link[chain_idx + 1],
593 type->stride);
594 offset = nir_iadd(&b->nb, offset, row_offset);
595 if (load)
596 *inout = vtn_create_ssa_value(b, glsl_scalar_type(base_type));
597 _vtn_load_store_tail(b, op, load, index, offset,
598 access_offset, access_size,
599 inout, glsl_scalar_type(base_type));
600 } else {
601 /* Grabbing a column; picking one element off each row */
602 unsigned num_comps = glsl_get_vector_elements(type->type);
603 const struct glsl_type *column_type =
604 glsl_get_column_type(type->type);
605
606 nir_ssa_def *comps[4];
607 for (unsigned i = 0; i < num_comps; i++) {
608 nir_ssa_def *elem_offset =
609 nir_iadd(&b->nb, offset,
610 nir_imm_int(&b->nb, i * type->stride));
611
612 struct vtn_ssa_value *comp, temp_val;
613 if (!load) {
614 temp_val.def = nir_channel(&b->nb, (*inout)->def, i);
615 temp_val.type = glsl_scalar_type(base_type);
616 }
617 comp = &temp_val;
618 _vtn_load_store_tail(b, op, load, index, elem_offset,
619 access_offset, access_size,
620 &comp, glsl_scalar_type(base_type));
621 comps[i] = comp->def;
622 }
623
624 if (load) {
625 if (*inout == NULL)
626 *inout = vtn_create_ssa_value(b, column_type);
627
628 (*inout)->def = nir_vec(&b->nb, comps, num_comps);
629 }
630 }
631 } else {
632 /* Column-major with a deref. Fall through to array case. */
633 nir_ssa_def *col_offset =
634 vtn_access_link_as_ssa(b, chain->link[chain_idx], type->stride);
635 offset = nir_iadd(&b->nb, offset, col_offset);
636
637 _vtn_block_load_store(b, op, load, index, offset,
638 access_offset, access_size,
639 chain, chain_idx + 1,
640 type->array_element, inout);
641 }
642 } else if (chain == NULL) {
643 /* Single whole vector */
644 assert(glsl_type_is_vector_or_scalar(type->type));
645 _vtn_load_store_tail(b, op, load, index, offset,
646 access_offset, access_size,
647 inout, type->type);
648 } else {
649 /* Single component of a vector. Fall through to array case. */
650 nir_ssa_def *elem_offset =
651 vtn_access_link_as_ssa(b, chain->link[chain_idx], type->stride);
652 offset = nir_iadd(&b->nb, offset, elem_offset);
653
654 _vtn_block_load_store(b, op, load, index, offset,
655 access_offset, access_size,
656 NULL, 0,
657 type->array_element, inout);
658 }
659 return;
660
661 case GLSL_TYPE_ARRAY: {
662 unsigned elems = glsl_get_length(type->type);
663 for (unsigned i = 0; i < elems; i++) {
664 nir_ssa_def *elem_off =
665 nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, i * type->stride));
666 _vtn_block_load_store(b, op, load, index, elem_off,
667 access_offset, access_size,
668 NULL, 0,
669 type->array_element, &(*inout)->elems[i]);
670 }
671 return;
672 }
673
674 case GLSL_TYPE_STRUCT: {
675 unsigned elems = glsl_get_length(type->type);
676 for (unsigned i = 0; i < elems; i++) {
677 nir_ssa_def *elem_off =
678 nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, type->offsets[i]));
679 _vtn_block_load_store(b, op, load, index, elem_off,
680 access_offset, access_size,
681 NULL, 0,
682 type->members[i], &(*inout)->elems[i]);
683 }
684 return;
685 }
686
687 default:
688 unreachable("Invalid block member type");
689 }
690 }
691
692 static struct vtn_ssa_value *
693 vtn_block_load(struct vtn_builder *b, struct vtn_access_chain *src)
694 {
695 nir_intrinsic_op op;
696 unsigned access_offset = 0, access_size = 0;
697 switch (src->var->mode) {
698 case vtn_variable_mode_ubo:
699 op = nir_intrinsic_load_ubo;
700 break;
701 case vtn_variable_mode_ssbo:
702 op = nir_intrinsic_load_ssbo;
703 break;
704 case vtn_variable_mode_push_constant:
705 op = nir_intrinsic_load_push_constant;
706 vtn_access_chain_get_offset_size(src, &access_offset, &access_size);
707 break;
708 default:
709 assert(!"Invalid block variable mode");
710 }
711
712 nir_ssa_def *offset, *index = NULL;
713 struct vtn_type *type;
714 unsigned chain_idx;
715 offset = vtn_access_chain_to_offset(b, src, &index, &type, &chain_idx, true);
716
717 struct vtn_ssa_value *value = NULL;
718 _vtn_block_load_store(b, op, true, index, offset,
719 access_offset, access_size,
720 src, chain_idx, type, &value);
721 return value;
722 }
723
724 static void
725 vtn_block_store(struct vtn_builder *b, struct vtn_ssa_value *src,
726 struct vtn_access_chain *dst)
727 {
728 nir_ssa_def *offset, *index = NULL;
729 struct vtn_type *type;
730 unsigned chain_idx;
731 offset = vtn_access_chain_to_offset(b, dst, &index, &type, &chain_idx, true);
732
733 _vtn_block_load_store(b, nir_intrinsic_store_ssbo, false, index, offset,
734 0, 0, dst, chain_idx, type, &src);
735 }
736
737 static bool
738 vtn_variable_is_external_block(struct vtn_variable *var)
739 {
740 return var->mode == vtn_variable_mode_ssbo ||
741 var->mode == vtn_variable_mode_ubo ||
742 var->mode == vtn_variable_mode_push_constant;
743 }
744
745 static void
746 _vtn_variable_load_store(struct vtn_builder *b, bool load,
747 struct vtn_access_chain *chain,
748 struct vtn_type *tail_type,
749 struct vtn_ssa_value **inout)
750 {
751 enum glsl_base_type base_type = glsl_get_base_type(tail_type->type);
752 switch (base_type) {
753 case GLSL_TYPE_UINT:
754 case GLSL_TYPE_INT:
755 case GLSL_TYPE_UINT64:
756 case GLSL_TYPE_INT64:
757 case GLSL_TYPE_FLOAT:
758 case GLSL_TYPE_BOOL:
759 case GLSL_TYPE_DOUBLE:
760 /* At this point, we have a scalar, vector, or matrix so we know that
761 * there cannot be any structure splitting still in the way. By
762 * stopping at the matrix level rather than the vector level, we
763 * ensure that matrices get loaded in the optimal way even if they
764 * are storred row-major in a UBO.
765 */
766 if (load) {
767 *inout = vtn_local_load(b, vtn_access_chain_to_deref(b, chain));
768 } else {
769 vtn_local_store(b, *inout, vtn_access_chain_to_deref(b, chain));
770 }
771 return;
772
773 case GLSL_TYPE_ARRAY:
774 case GLSL_TYPE_STRUCT: {
775 struct vtn_access_chain *new_chain =
776 vtn_access_chain_extend(b, chain, 1);
777 new_chain->link[chain->length].mode = vtn_access_mode_literal;
778 unsigned elems = glsl_get_length(tail_type->type);
779 if (load) {
780 assert(*inout == NULL);
781 *inout = rzalloc(b, struct vtn_ssa_value);
782 (*inout)->type = tail_type->type;
783 (*inout)->elems = rzalloc_array(b, struct vtn_ssa_value *, elems);
784 }
785 for (unsigned i = 0; i < elems; i++) {
786 new_chain->link[chain->length].id = i;
787 struct vtn_type *elem_type = base_type == GLSL_TYPE_ARRAY ?
788 tail_type->array_element : tail_type->members[i];
789 _vtn_variable_load_store(b, load, new_chain, elem_type,
790 &(*inout)->elems[i]);
791 }
792 return;
793 }
794
795 default:
796 unreachable("Invalid access chain type");
797 }
798 }
799
800 struct vtn_ssa_value *
801 vtn_variable_load(struct vtn_builder *b, struct vtn_access_chain *src)
802 {
803 if (vtn_variable_is_external_block(src->var)) {
804 return vtn_block_load(b, src);
805 } else {
806 struct vtn_type *tail_type = vtn_access_chain_tail_type(b, src);
807 struct vtn_ssa_value *val = NULL;
808 _vtn_variable_load_store(b, true, src, tail_type, &val);
809 return val;
810 }
811 }
812
813 void
814 vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,
815 struct vtn_access_chain *dest)
816 {
817 if (vtn_variable_is_external_block(dest->var)) {
818 assert(dest->var->mode == vtn_variable_mode_ssbo);
819 vtn_block_store(b, src, dest);
820 } else {
821 struct vtn_type *tail_type = vtn_access_chain_tail_type(b, dest);
822 _vtn_variable_load_store(b, false, dest, tail_type, &src);
823 }
824 }
825
826 static void
827 _vtn_variable_copy(struct vtn_builder *b, struct vtn_access_chain *dest,
828 struct vtn_access_chain *src, struct vtn_type *tail_type)
829 {
830 enum glsl_base_type base_type = glsl_get_base_type(tail_type->type);
831 switch (base_type) {
832 case GLSL_TYPE_UINT:
833 case GLSL_TYPE_INT:
834 case GLSL_TYPE_UINT64:
835 case GLSL_TYPE_INT64:
836 case GLSL_TYPE_FLOAT:
837 case GLSL_TYPE_DOUBLE:
838 case GLSL_TYPE_BOOL:
839 /* At this point, we have a scalar, vector, or matrix so we know that
840 * there cannot be any structure splitting still in the way. By
841 * stopping at the matrix level rather than the vector level, we
842 * ensure that matrices get loaded in the optimal way even if they
843 * are storred row-major in a UBO.
844 */
845 vtn_variable_store(b, vtn_variable_load(b, src), dest);
846 return;
847
848 case GLSL_TYPE_ARRAY:
849 case GLSL_TYPE_STRUCT: {
850 struct vtn_access_chain *new_src, *new_dest;
851 new_src = vtn_access_chain_extend(b, src, 1);
852 new_dest = vtn_access_chain_extend(b, dest, 1);
853 new_src->link[src->length].mode = vtn_access_mode_literal;
854 new_dest->link[dest->length].mode = vtn_access_mode_literal;
855 unsigned elems = glsl_get_length(tail_type->type);
856 for (unsigned i = 0; i < elems; i++) {
857 new_src->link[src->length].id = i;
858 new_dest->link[dest->length].id = i;
859 struct vtn_type *elem_type = base_type == GLSL_TYPE_ARRAY ?
860 tail_type->array_element : tail_type->members[i];
861 _vtn_variable_copy(b, new_dest, new_src, elem_type);
862 }
863 return;
864 }
865
866 default:
867 unreachable("Invalid access chain type");
868 }
869 }
870
871 static void
872 vtn_variable_copy(struct vtn_builder *b, struct vtn_access_chain *dest,
873 struct vtn_access_chain *src)
874 {
875 struct vtn_type *tail_type = vtn_access_chain_tail_type(b, src);
876 assert(vtn_access_chain_tail_type(b, dest)->type == tail_type->type);
877
878 /* TODO: At some point, we should add a special-case for when we can
879 * just emit a copy_var intrinsic.
880 */
881 _vtn_variable_copy(b, dest, src, tail_type);
882 }
883
884 static void
885 set_mode_system_value(nir_variable_mode *mode)
886 {
887 assert(*mode == nir_var_system_value || *mode == nir_var_shader_in);
888 *mode = nir_var_system_value;
889 }
890
891 static void
892 vtn_get_builtin_location(struct vtn_builder *b,
893 SpvBuiltIn builtin, int *location,
894 nir_variable_mode *mode)
895 {
896 switch (builtin) {
897 case SpvBuiltInPosition:
898 *location = VARYING_SLOT_POS;
899 break;
900 case SpvBuiltInPointSize:
901 *location = VARYING_SLOT_PSIZ;
902 break;
903 case SpvBuiltInClipDistance:
904 *location = VARYING_SLOT_CLIP_DIST0; /* XXX CLIP_DIST1? */
905 break;
906 case SpvBuiltInCullDistance:
907 *location = VARYING_SLOT_CULL_DIST0;
908 break;
909 case SpvBuiltInVertexIndex:
910 *location = SYSTEM_VALUE_VERTEX_ID;
911 set_mode_system_value(mode);
912 break;
913 case SpvBuiltInVertexId:
914 /* Vulkan defines VertexID to be zero-based and reserves the new
915 * builtin keyword VertexIndex to indicate the non-zero-based value.
916 */
917 *location = SYSTEM_VALUE_VERTEX_ID_ZERO_BASE;
918 set_mode_system_value(mode);
919 break;
920 case SpvBuiltInInstanceIndex:
921 *location = SYSTEM_VALUE_INSTANCE_INDEX;
922 set_mode_system_value(mode);
923 break;
924 case SpvBuiltInInstanceId:
925 *location = SYSTEM_VALUE_INSTANCE_ID;
926 set_mode_system_value(mode);
927 break;
928 case SpvBuiltInPrimitiveId:
929 if (b->shader->stage == MESA_SHADER_FRAGMENT) {
930 assert(*mode == nir_var_shader_in);
931 *location = VARYING_SLOT_PRIMITIVE_ID;
932 } else if (*mode == nir_var_shader_out) {
933 *location = VARYING_SLOT_PRIMITIVE_ID;
934 } else {
935 *location = SYSTEM_VALUE_PRIMITIVE_ID;
936 set_mode_system_value(mode);
937 }
938 break;
939 case SpvBuiltInInvocationId:
940 *location = SYSTEM_VALUE_INVOCATION_ID;
941 set_mode_system_value(mode);
942 break;
943 case SpvBuiltInLayer:
944 *location = VARYING_SLOT_LAYER;
945 if (b->shader->stage == MESA_SHADER_FRAGMENT)
946 *mode = nir_var_shader_in;
947 else if (b->shader->stage == MESA_SHADER_GEOMETRY)
948 *mode = nir_var_shader_out;
949 else
950 unreachable("invalid stage for SpvBuiltInLayer");
951 break;
952 case SpvBuiltInViewportIndex:
953 *location = VARYING_SLOT_VIEWPORT;
954 if (b->shader->stage == MESA_SHADER_GEOMETRY)
955 *mode = nir_var_shader_out;
956 else if (b->shader->stage == MESA_SHADER_FRAGMENT)
957 *mode = nir_var_shader_in;
958 else
959 unreachable("invalid stage for SpvBuiltInViewportIndex");
960 break;
961 case SpvBuiltInTessLevelOuter:
962 *location = VARYING_SLOT_TESS_LEVEL_OUTER;
963 break;
964 case SpvBuiltInTessLevelInner:
965 *location = VARYING_SLOT_TESS_LEVEL_INNER;
966 break;
967 case SpvBuiltInTessCoord:
968 *location = SYSTEM_VALUE_TESS_COORD;
969 set_mode_system_value(mode);
970 break;
971 case SpvBuiltInPatchVertices:
972 *location = SYSTEM_VALUE_VERTICES_IN;
973 set_mode_system_value(mode);
974 break;
975 case SpvBuiltInFragCoord:
976 *location = VARYING_SLOT_POS;
977 assert(*mode == nir_var_shader_in);
978 break;
979 case SpvBuiltInPointCoord:
980 *location = VARYING_SLOT_PNTC;
981 assert(*mode == nir_var_shader_in);
982 break;
983 case SpvBuiltInFrontFacing:
984 *location = SYSTEM_VALUE_FRONT_FACE;
985 set_mode_system_value(mode);
986 break;
987 case SpvBuiltInSampleId:
988 *location = SYSTEM_VALUE_SAMPLE_ID;
989 set_mode_system_value(mode);
990 break;
991 case SpvBuiltInSamplePosition:
992 *location = SYSTEM_VALUE_SAMPLE_POS;
993 set_mode_system_value(mode);
994 break;
995 case SpvBuiltInSampleMask:
996 if (*mode == nir_var_shader_out) {
997 *location = FRAG_RESULT_SAMPLE_MASK;
998 } else {
999 *location = SYSTEM_VALUE_SAMPLE_MASK_IN;
1000 set_mode_system_value(mode);
1001 }
1002 break;
1003 case SpvBuiltInFragDepth:
1004 *location = FRAG_RESULT_DEPTH;
1005 assert(*mode == nir_var_shader_out);
1006 break;
1007 case SpvBuiltInNumWorkgroups:
1008 *location = SYSTEM_VALUE_NUM_WORK_GROUPS;
1009 set_mode_system_value(mode);
1010 break;
1011 case SpvBuiltInWorkgroupSize:
1012 /* This should already be handled */
1013 unreachable("unsupported builtin");
1014 break;
1015 case SpvBuiltInWorkgroupId:
1016 *location = SYSTEM_VALUE_WORK_GROUP_ID;
1017 set_mode_system_value(mode);
1018 break;
1019 case SpvBuiltInLocalInvocationId:
1020 *location = SYSTEM_VALUE_LOCAL_INVOCATION_ID;
1021 set_mode_system_value(mode);
1022 break;
1023 case SpvBuiltInLocalInvocationIndex:
1024 *location = SYSTEM_VALUE_LOCAL_INVOCATION_INDEX;
1025 set_mode_system_value(mode);
1026 break;
1027 case SpvBuiltInGlobalInvocationId:
1028 *location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID;
1029 set_mode_system_value(mode);
1030 break;
1031 case SpvBuiltInBaseVertex:
1032 *location = SYSTEM_VALUE_BASE_VERTEX;
1033 set_mode_system_value(mode);
1034 break;
1035 case SpvBuiltInBaseInstance:
1036 *location = SYSTEM_VALUE_BASE_INSTANCE;
1037 set_mode_system_value(mode);
1038 break;
1039 case SpvBuiltInDrawIndex:
1040 *location = SYSTEM_VALUE_DRAW_ID;
1041 set_mode_system_value(mode);
1042 break;
1043 case SpvBuiltInViewIndex:
1044 *location = SYSTEM_VALUE_VIEW_INDEX;
1045 set_mode_system_value(mode);
1046 break;
1047 case SpvBuiltInHelperInvocation:
1048 default:
1049 unreachable("unsupported builtin");
1050 }
1051 }
1052
1053 static void
1054 apply_var_decoration(struct vtn_builder *b, nir_variable *nir_var,
1055 const struct vtn_decoration *dec)
1056 {
1057 switch (dec->decoration) {
1058 case SpvDecorationRelaxedPrecision:
1059 break; /* FIXME: Do nothing with this for now. */
1060 case SpvDecorationNoPerspective:
1061 nir_var->data.interpolation = INTERP_MODE_NOPERSPECTIVE;
1062 break;
1063 case SpvDecorationFlat:
1064 nir_var->data.interpolation = INTERP_MODE_FLAT;
1065 break;
1066 case SpvDecorationCentroid:
1067 nir_var->data.centroid = true;
1068 break;
1069 case SpvDecorationSample:
1070 nir_var->data.sample = true;
1071 break;
1072 case SpvDecorationInvariant:
1073 nir_var->data.invariant = true;
1074 break;
1075 case SpvDecorationConstant:
1076 assert(nir_var->constant_initializer != NULL);
1077 nir_var->data.read_only = true;
1078 break;
1079 case SpvDecorationNonReadable:
1080 nir_var->data.image.write_only = true;
1081 break;
1082 case SpvDecorationNonWritable:
1083 nir_var->data.read_only = true;
1084 nir_var->data.image.read_only = true;
1085 break;
1086 case SpvDecorationComponent:
1087 nir_var->data.location_frac = dec->literals[0];
1088 break;
1089 case SpvDecorationIndex:
1090 nir_var->data.index = dec->literals[0];
1091 break;
1092 case SpvDecorationBuiltIn: {
1093 SpvBuiltIn builtin = dec->literals[0];
1094
1095 if (builtin == SpvBuiltInWorkgroupSize) {
1096 /* This shouldn't be a builtin. It's actually a constant. */
1097 nir_var->data.mode = nir_var_global;
1098 nir_var->data.read_only = true;
1099
1100 nir_constant *c = rzalloc(nir_var, nir_constant);
1101 c->values[0].u32[0] = b->shader->info.cs.local_size[0];
1102 c->values[0].u32[1] = b->shader->info.cs.local_size[1];
1103 c->values[0].u32[2] = b->shader->info.cs.local_size[2];
1104 nir_var->constant_initializer = c;
1105 break;
1106 }
1107
1108 nir_variable_mode mode = nir_var->data.mode;
1109 vtn_get_builtin_location(b, builtin, &nir_var->data.location, &mode);
1110 nir_var->data.mode = mode;
1111
1112 switch (builtin) {
1113 case SpvBuiltInTessLevelOuter:
1114 case SpvBuiltInTessLevelInner:
1115 nir_var->data.compact = true;
1116 break;
1117 case SpvBuiltInSamplePosition:
1118 nir_var->data.origin_upper_left = b->origin_upper_left;
1119 /* fallthrough */
1120 case SpvBuiltInFragCoord:
1121 nir_var->data.pixel_center_integer = b->pixel_center_integer;
1122 break;
1123 default:
1124 break;
1125 }
1126 }
1127
1128 case SpvDecorationSpecId:
1129 case SpvDecorationRowMajor:
1130 case SpvDecorationColMajor:
1131 case SpvDecorationMatrixStride:
1132 case SpvDecorationRestrict:
1133 case SpvDecorationAliased:
1134 case SpvDecorationVolatile:
1135 case SpvDecorationCoherent:
1136 case SpvDecorationUniform:
1137 case SpvDecorationStream:
1138 case SpvDecorationOffset:
1139 case SpvDecorationLinkageAttributes:
1140 break; /* Do nothing with these here */
1141
1142 case SpvDecorationPatch:
1143 nir_var->data.patch = true;
1144 break;
1145
1146 case SpvDecorationLocation:
1147 unreachable("Handled above");
1148
1149 case SpvDecorationBlock:
1150 case SpvDecorationBufferBlock:
1151 case SpvDecorationArrayStride:
1152 case SpvDecorationGLSLShared:
1153 case SpvDecorationGLSLPacked:
1154 break; /* These can apply to a type but we don't care about them */
1155
1156 case SpvDecorationBinding:
1157 case SpvDecorationDescriptorSet:
1158 case SpvDecorationNoContraction:
1159 case SpvDecorationInputAttachmentIndex:
1160 vtn_warn("Decoration not allowed for variable or structure member: %s",
1161 spirv_decoration_to_string(dec->decoration));
1162 break;
1163
1164 case SpvDecorationXfbBuffer:
1165 case SpvDecorationXfbStride:
1166 vtn_warn("Vulkan does not have transform feedback: %s",
1167 spirv_decoration_to_string(dec->decoration));
1168 break;
1169
1170 case SpvDecorationCPacked:
1171 case SpvDecorationSaturatedConversion:
1172 case SpvDecorationFuncParamAttr:
1173 case SpvDecorationFPRoundingMode:
1174 case SpvDecorationFPFastMathMode:
1175 case SpvDecorationAlignment:
1176 vtn_warn("Decoration only allowed for CL-style kernels: %s",
1177 spirv_decoration_to_string(dec->decoration));
1178 break;
1179
1180 default:
1181 unreachable("Unhandled decoration");
1182 }
1183 }
1184
1185 static void
1186 var_is_patch_cb(struct vtn_builder *b, struct vtn_value *val, int member,
1187 const struct vtn_decoration *dec, void *out_is_patch)
1188 {
1189 if (dec->decoration == SpvDecorationPatch) {
1190 *((bool *) out_is_patch) = true;
1191 }
1192 }
1193
1194 static void
1195 var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
1196 const struct vtn_decoration *dec, void *void_var)
1197 {
1198 struct vtn_variable *vtn_var = void_var;
1199
1200 /* Handle decorations that apply to a vtn_variable as a whole */
1201 switch (dec->decoration) {
1202 case SpvDecorationBinding:
1203 vtn_var->binding = dec->literals[0];
1204 return;
1205 case SpvDecorationDescriptorSet:
1206 vtn_var->descriptor_set = dec->literals[0];
1207 return;
1208 case SpvDecorationInputAttachmentIndex:
1209 vtn_var->input_attachment_index = dec->literals[0];
1210 return;
1211 case SpvDecorationPatch:
1212 vtn_var->patch = true;
1213 break;
1214 default:
1215 break;
1216 }
1217
1218 if (val->value_type == vtn_value_type_access_chain) {
1219 assert(val->access_chain->length == 0);
1220 assert(val->access_chain->var == void_var);
1221 assert(member == -1);
1222 } else {
1223 assert(val->value_type == vtn_value_type_type);
1224 }
1225
1226 /* Location is odd. If applied to a split structure, we have to walk the
1227 * whole thing and accumulate the location. It's easier to handle as a
1228 * special case.
1229 */
1230 if (dec->decoration == SpvDecorationLocation) {
1231 unsigned location = dec->literals[0];
1232 bool is_vertex_input;
1233 if (b->shader->stage == MESA_SHADER_FRAGMENT &&
1234 vtn_var->mode == vtn_variable_mode_output) {
1235 is_vertex_input = false;
1236 location += FRAG_RESULT_DATA0;
1237 } else if (b->shader->stage == MESA_SHADER_VERTEX &&
1238 vtn_var->mode == vtn_variable_mode_input) {
1239 is_vertex_input = true;
1240 location += VERT_ATTRIB_GENERIC0;
1241 } else if (vtn_var->mode == vtn_variable_mode_input ||
1242 vtn_var->mode == vtn_variable_mode_output) {
1243 is_vertex_input = false;
1244 location += vtn_var->patch ? VARYING_SLOT_PATCH0 : VARYING_SLOT_VAR0;
1245 } else {
1246 vtn_warn("Location must be on input or output variable");
1247 return;
1248 }
1249
1250 if (vtn_var->var) {
1251 /* This handles the member and lone variable cases */
1252 vtn_var->var->data.location = location;
1253 } else {
1254 /* This handles the structure member case */
1255 assert(vtn_var->members);
1256 unsigned length =
1257 glsl_get_length(glsl_without_array(vtn_var->type->type));
1258 for (unsigned i = 0; i < length; i++) {
1259 vtn_var->members[i]->data.location = location;
1260 location +=
1261 glsl_count_attribute_slots(vtn_var->members[i]->interface_type,
1262 is_vertex_input);
1263 }
1264 }
1265 return;
1266 } else {
1267 if (vtn_var->var) {
1268 assert(member <= 0);
1269 apply_var_decoration(b, vtn_var->var, dec);
1270 } else if (vtn_var->members) {
1271 if (member >= 0) {
1272 assert(vtn_var->members);
1273 apply_var_decoration(b, vtn_var->members[member], dec);
1274 } else {
1275 unsigned length =
1276 glsl_get_length(glsl_without_array(vtn_var->type->type));
1277 for (unsigned i = 0; i < length; i++)
1278 apply_var_decoration(b, vtn_var->members[i], dec);
1279 }
1280 } else {
1281 /* A few variables, those with external storage, have no actual
1282 * nir_variables associated with them. Fortunately, all decorations
1283 * we care about for those variables are on the type only.
1284 */
1285 assert(vtn_var->mode == vtn_variable_mode_ubo ||
1286 vtn_var->mode == vtn_variable_mode_ssbo ||
1287 vtn_var->mode == vtn_variable_mode_push_constant);
1288 }
1289 }
1290 }
1291
1292 static enum vtn_variable_mode
1293 vtn_storage_class_to_mode(SpvStorageClass class,
1294 struct vtn_type *interface_type,
1295 nir_variable_mode *nir_mode_out)
1296 {
1297 enum vtn_variable_mode mode;
1298 nir_variable_mode nir_mode;
1299 switch (class) {
1300 case SpvStorageClassUniform:
1301 case SpvStorageClassUniformConstant:
1302 if (interface_type->block) {
1303 mode = vtn_variable_mode_ubo;
1304 nir_mode = 0;
1305 } else if (interface_type->buffer_block) {
1306 mode = vtn_variable_mode_ssbo;
1307 nir_mode = 0;
1308 } else if (glsl_type_is_image(interface_type->type)) {
1309 mode = vtn_variable_mode_image;
1310 nir_mode = nir_var_uniform;
1311 } else if (glsl_type_is_sampler(interface_type->type)) {
1312 mode = vtn_variable_mode_sampler;
1313 nir_mode = nir_var_uniform;
1314 } else {
1315 assert(!"Invalid uniform variable type");
1316 }
1317 break;
1318 case SpvStorageClassPushConstant:
1319 mode = vtn_variable_mode_push_constant;
1320 nir_mode = nir_var_uniform;
1321 break;
1322 case SpvStorageClassInput:
1323 mode = vtn_variable_mode_input;
1324 nir_mode = nir_var_shader_in;
1325 break;
1326 case SpvStorageClassOutput:
1327 mode = vtn_variable_mode_output;
1328 nir_mode = nir_var_shader_out;
1329 break;
1330 case SpvStorageClassPrivate:
1331 mode = vtn_variable_mode_global;
1332 nir_mode = nir_var_global;
1333 break;
1334 case SpvStorageClassFunction:
1335 mode = vtn_variable_mode_local;
1336 nir_mode = nir_var_local;
1337 break;
1338 case SpvStorageClassWorkgroup:
1339 mode = vtn_variable_mode_workgroup;
1340 nir_mode = nir_var_shared;
1341 break;
1342 case SpvStorageClassCrossWorkgroup:
1343 case SpvStorageClassGeneric:
1344 case SpvStorageClassAtomicCounter:
1345 default:
1346 unreachable("Unhandled variable storage class");
1347 }
1348
1349 if (nir_mode_out)
1350 *nir_mode_out = nir_mode;
1351
1352 return mode;
1353 }
1354
1355 static bool
1356 is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage stage)
1357 {
1358 if (var->patch || !glsl_type_is_array(var->type->type))
1359 return false;
1360
1361 if (var->mode == vtn_variable_mode_input) {
1362 return stage == MESA_SHADER_TESS_CTRL ||
1363 stage == MESA_SHADER_TESS_EVAL ||
1364 stage == MESA_SHADER_GEOMETRY;
1365 }
1366
1367 if (var->mode == vtn_variable_mode_output)
1368 return stage == MESA_SHADER_TESS_CTRL;
1369
1370 return false;
1371 }
1372
1373 void
1374 vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
1375 const uint32_t *w, unsigned count)
1376 {
1377 switch (opcode) {
1378 case SpvOpUndef: {
1379 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);
1380 val->type = vtn_value(b, w[1], vtn_value_type_type)->type;
1381 break;
1382 }
1383
1384 case SpvOpVariable: {
1385 struct vtn_variable *var = rzalloc(b, struct vtn_variable);
1386 var->type = vtn_value(b, w[1], vtn_value_type_type)->type;
1387
1388 var->chain.var = var;
1389 var->chain.length = 0;
1390
1391 struct vtn_value *val =
1392 vtn_push_value(b, w[2], vtn_value_type_access_chain);
1393 val->access_chain = &var->chain;
1394
1395 struct vtn_type *without_array = var->type;
1396 while(glsl_type_is_array(without_array->type))
1397 without_array = without_array->array_element;
1398
1399 nir_variable_mode nir_mode;
1400 var->mode = vtn_storage_class_to_mode(w[3], without_array, &nir_mode);
1401
1402 switch (var->mode) {
1403 case vtn_variable_mode_ubo:
1404 b->shader->info.num_ubos++;
1405 break;
1406 case vtn_variable_mode_ssbo:
1407 b->shader->info.num_ssbos++;
1408 break;
1409 case vtn_variable_mode_image:
1410 b->shader->info.num_images++;
1411 break;
1412 case vtn_variable_mode_sampler:
1413 b->shader->info.num_textures++;
1414 break;
1415 case vtn_variable_mode_push_constant:
1416 b->shader->num_uniforms = vtn_type_block_size(var->type);
1417 break;
1418 default:
1419 /* No tallying is needed */
1420 break;
1421 }
1422
1423 switch (var->mode) {
1424 case vtn_variable_mode_local:
1425 case vtn_variable_mode_global:
1426 case vtn_variable_mode_image:
1427 case vtn_variable_mode_sampler:
1428 case vtn_variable_mode_workgroup:
1429 /* For these, we create the variable normally */
1430 var->var = rzalloc(b->shader, nir_variable);
1431 var->var->name = ralloc_strdup(var->var, val->name);
1432 var->var->type = var->type->type;
1433 var->var->data.mode = nir_mode;
1434
1435 switch (var->mode) {
1436 case vtn_variable_mode_image:
1437 case vtn_variable_mode_sampler:
1438 var->var->interface_type = without_array->type;
1439 break;
1440 default:
1441 var->var->interface_type = NULL;
1442 break;
1443 }
1444 break;
1445
1446 case vtn_variable_mode_input:
1447 case vtn_variable_mode_output: {
1448 /* In order to know whether or not we're a per-vertex inout, we need
1449 * the patch qualifier. This means walking the variable decorations
1450 * early before we actually create any variables. Not a big deal.
1451 *
1452 * GLSLang really likes to place decorations in the most interior
1453 * thing it possibly can. In particular, if you have a struct, it
1454 * will place the patch decorations on the struct members. This
1455 * should be handled by the variable splitting below just fine.
1456 *
1457 * If you have an array-of-struct, things get even more weird as it
1458 * will place the patch decorations on the struct even though it's
1459 * inside an array and some of the members being patch and others not
1460 * makes no sense whatsoever. Since the only sensible thing is for
1461 * it to be all or nothing, we'll call it patch if any of the members
1462 * are declared patch.
1463 */
1464 var->patch = false;
1465 vtn_foreach_decoration(b, val, var_is_patch_cb, &var->patch);
1466 if (glsl_type_is_array(var->type->type) &&
1467 glsl_type_is_struct(without_array->type)) {
1468 vtn_foreach_decoration(b, without_array->val,
1469 var_is_patch_cb, &var->patch);
1470 }
1471
1472 /* For inputs and outputs, we immediately split structures. This
1473 * is for a couple of reasons. For one, builtins may all come in
1474 * a struct and we really want those split out into separate
1475 * variables. For another, interpolation qualifiers can be
1476 * applied to members of the top-level struct ane we need to be
1477 * able to preserve that information.
1478 */
1479
1480 int array_length = -1;
1481 struct vtn_type *interface_type = var->type;
1482 if (is_per_vertex_inout(var, b->shader->stage)) {
1483 /* In Geometry shaders (and some tessellation), inputs come
1484 * in per-vertex arrays. However, some builtins come in
1485 * non-per-vertex, hence the need for the is_array check. In
1486 * any case, there are no non-builtin arrays allowed so this
1487 * check should be sufficient.
1488 */
1489 interface_type = var->type->array_element;
1490 array_length = glsl_get_length(var->type->type);
1491 }
1492
1493 if (glsl_type_is_struct(interface_type->type)) {
1494 /* It's a struct. Split it. */
1495 unsigned num_members = glsl_get_length(interface_type->type);
1496 var->members = ralloc_array(b, nir_variable *, num_members);
1497
1498 for (unsigned i = 0; i < num_members; i++) {
1499 const struct glsl_type *mtype = interface_type->members[i]->type;
1500 if (array_length >= 0)
1501 mtype = glsl_array_type(mtype, array_length);
1502
1503 var->members[i] = rzalloc(b->shader, nir_variable);
1504 var->members[i]->name =
1505 ralloc_asprintf(var->members[i], "%s.%d", val->name, i);
1506 var->members[i]->type = mtype;
1507 var->members[i]->interface_type =
1508 interface_type->members[i]->type;
1509 var->members[i]->data.mode = nir_mode;
1510 var->members[i]->data.patch = var->patch;
1511 }
1512 } else {
1513 var->var = rzalloc(b->shader, nir_variable);
1514 var->var->name = ralloc_strdup(var->var, val->name);
1515 var->var->type = var->type->type;
1516 var->var->interface_type = interface_type->type;
1517 var->var->data.mode = nir_mode;
1518 var->var->data.patch = var->patch;
1519 }
1520
1521 /* For inputs and outputs, we need to grab locations and builtin
1522 * information from the interface type.
1523 */
1524 vtn_foreach_decoration(b, interface_type->val, var_decoration_cb, var);
1525 break;
1526 }
1527
1528 case vtn_variable_mode_param:
1529 unreachable("Not created through OpVariable");
1530
1531 case vtn_variable_mode_ubo:
1532 case vtn_variable_mode_ssbo:
1533 case vtn_variable_mode_push_constant:
1534 /* These don't need actual variables. */
1535 break;
1536 }
1537
1538 if (count > 4) {
1539 assert(count == 5);
1540 nir_constant *constant =
1541 vtn_value(b, w[4], vtn_value_type_constant)->constant;
1542 var->var->constant_initializer =
1543 nir_constant_clone(constant, var->var);
1544 }
1545
1546 vtn_foreach_decoration(b, val, var_decoration_cb, var);
1547
1548 if (var->mode == vtn_variable_mode_image ||
1549 var->mode == vtn_variable_mode_sampler) {
1550 /* XXX: We still need the binding information in the nir_variable
1551 * for these. We should fix that.
1552 */
1553 var->var->data.binding = var->binding;
1554 var->var->data.descriptor_set = var->descriptor_set;
1555 var->var->data.index = var->input_attachment_index;
1556
1557 if (var->mode == vtn_variable_mode_image)
1558 var->var->data.image.format = without_array->image_format;
1559 }
1560
1561 if (var->mode == vtn_variable_mode_local) {
1562 assert(var->members == NULL && var->var != NULL);
1563 nir_function_impl_add_variable(b->impl, var->var);
1564 } else if (var->var) {
1565 nir_shader_add_variable(b->shader, var->var);
1566 } else if (var->members) {
1567 unsigned count = glsl_get_length(without_array->type);
1568 for (unsigned i = 0; i < count; i++) {
1569 assert(var->members[i]->data.mode != nir_var_local);
1570 nir_shader_add_variable(b->shader, var->members[i]);
1571 }
1572 } else {
1573 assert(var->mode == vtn_variable_mode_ubo ||
1574 var->mode == vtn_variable_mode_ssbo ||
1575 var->mode == vtn_variable_mode_push_constant);
1576 }
1577 break;
1578 }
1579
1580 case SpvOpAccessChain:
1581 case SpvOpInBoundsAccessChain: {
1582 struct vtn_access_chain *base, *chain;
1583 struct vtn_value *base_val = vtn_untyped_value(b, w[3]);
1584 if (base_val->value_type == vtn_value_type_sampled_image) {
1585 /* This is rather insane. SPIR-V allows you to use OpSampledImage
1586 * to combine an array of images with a single sampler to get an
1587 * array of sampled images that all share the same sampler.
1588 * Fortunately, this means that we can more-or-less ignore the
1589 * sampler when crawling the access chain, but it does leave us
1590 * with this rather awkward little special-case.
1591 */
1592 base = base_val->sampled_image->image;
1593 } else {
1594 assert(base_val->value_type == vtn_value_type_access_chain);
1595 base = base_val->access_chain;
1596 }
1597
1598 chain = vtn_access_chain_extend(b, base, count - 4);
1599
1600 unsigned idx = base->length;
1601 for (int i = 4; i < count; i++) {
1602 struct vtn_value *link_val = vtn_untyped_value(b, w[i]);
1603 if (link_val->value_type == vtn_value_type_constant) {
1604 chain->link[idx].mode = vtn_access_mode_literal;
1605 chain->link[idx].id = link_val->constant->values[0].u32[0];
1606 } else {
1607 chain->link[idx].mode = vtn_access_mode_id;
1608 chain->link[idx].id = w[i];
1609 }
1610 idx++;
1611 }
1612
1613 if (base_val->value_type == vtn_value_type_sampled_image) {
1614 struct vtn_value *val =
1615 vtn_push_value(b, w[2], vtn_value_type_sampled_image);
1616 val->sampled_image = ralloc(b, struct vtn_sampled_image);
1617 val->sampled_image->image = chain;
1618 val->sampled_image->sampler = base_val->sampled_image->sampler;
1619 } else {
1620 struct vtn_value *val =
1621 vtn_push_value(b, w[2], vtn_value_type_access_chain);
1622 val->access_chain = chain;
1623 }
1624 break;
1625 }
1626
1627 case SpvOpCopyMemory: {
1628 struct vtn_value *dest = vtn_value(b, w[1], vtn_value_type_access_chain);
1629 struct vtn_value *src = vtn_value(b, w[2], vtn_value_type_access_chain);
1630
1631 vtn_variable_copy(b, dest->access_chain, src->access_chain);
1632 break;
1633 }
1634
1635 case SpvOpLoad: {
1636 struct vtn_access_chain *src =
1637 vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
1638
1639 if (src->var->mode == vtn_variable_mode_image ||
1640 src->var->mode == vtn_variable_mode_sampler) {
1641 vtn_push_value(b, w[2], vtn_value_type_access_chain)->access_chain = src;
1642 return;
1643 }
1644
1645 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
1646 val->ssa = vtn_variable_load(b, src);
1647 break;
1648 }
1649
1650 case SpvOpStore: {
1651 struct vtn_access_chain *dest =
1652 vtn_value(b, w[1], vtn_value_type_access_chain)->access_chain;
1653
1654 if (glsl_type_is_sampler(dest->var->type->type)) {
1655 vtn_warn("OpStore of a sampler detected. Doing on-the-fly copy "
1656 "propagation to workaround the problem.");
1657 assert(dest->var->copy_prop_sampler == NULL);
1658 dest->var->copy_prop_sampler =
1659 vtn_value(b, w[2], vtn_value_type_access_chain)->access_chain;
1660 break;
1661 }
1662
1663 struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);
1664 vtn_variable_store(b, src, dest);
1665 break;
1666 }
1667
1668 case SpvOpArrayLength: {
1669 struct vtn_access_chain *chain =
1670 vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
1671
1672 const uint32_t offset = chain->var->type->offsets[w[4]];
1673 const uint32_t stride = chain->var->type->members[w[4]]->stride;
1674
1675 unsigned chain_idx;
1676 struct vtn_type *type;
1677 nir_ssa_def *index =
1678 get_vulkan_resource_index(b, chain, &type, &chain_idx);
1679
1680 nir_intrinsic_instr *instr =
1681 nir_intrinsic_instr_create(b->nb.shader,
1682 nir_intrinsic_get_buffer_size);
1683 instr->src[0] = nir_src_for_ssa(index);
1684 nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, NULL);
1685 nir_builder_instr_insert(&b->nb, &instr->instr);
1686 nir_ssa_def *buf_size = &instr->dest.ssa;
1687
1688 /* array_length = max(buffer_size - offset, 0) / stride */
1689 nir_ssa_def *array_length =
1690 nir_idiv(&b->nb,
1691 nir_imax(&b->nb,
1692 nir_isub(&b->nb,
1693 buf_size,
1694 nir_imm_int(&b->nb, offset)),
1695 nir_imm_int(&b->nb, 0u)),
1696 nir_imm_int(&b->nb, stride));
1697
1698 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
1699 val->ssa = vtn_create_ssa_value(b, glsl_uint_type());
1700 val->ssa->def = array_length;
1701 break;
1702 }
1703
1704 case SpvOpCopyMemorySized:
1705 default:
1706 unreachable("Unhandled opcode");
1707 }
1708 }