nir/spirv: Move a "}"
[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 bool
1293 is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage stage)
1294 {
1295 if (var->patch || !glsl_type_is_array(var->type->type))
1296 return false;
1297
1298 if (var->mode == vtn_variable_mode_input) {
1299 return stage == MESA_SHADER_TESS_CTRL ||
1300 stage == MESA_SHADER_TESS_EVAL ||
1301 stage == MESA_SHADER_GEOMETRY;
1302 }
1303
1304 if (var->mode == vtn_variable_mode_output)
1305 return stage == MESA_SHADER_TESS_CTRL;
1306
1307 return false;
1308 }
1309
1310 void
1311 vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
1312 const uint32_t *w, unsigned count)
1313 {
1314 switch (opcode) {
1315 case SpvOpUndef: {
1316 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);
1317 val->type = vtn_value(b, w[1], vtn_value_type_type)->type;
1318 break;
1319 }
1320
1321 case SpvOpVariable: {
1322 struct vtn_variable *var = rzalloc(b, struct vtn_variable);
1323 var->type = vtn_value(b, w[1], vtn_value_type_type)->type;
1324
1325 var->chain.var = var;
1326 var->chain.length = 0;
1327
1328 struct vtn_value *val =
1329 vtn_push_value(b, w[2], vtn_value_type_access_chain);
1330 val->access_chain = &var->chain;
1331
1332 struct vtn_type *without_array = var->type;
1333 while(glsl_type_is_array(without_array->type))
1334 without_array = without_array->array_element;
1335
1336 nir_variable_mode nir_mode;
1337 switch ((SpvStorageClass)w[3]) {
1338 case SpvStorageClassUniform:
1339 case SpvStorageClassUniformConstant:
1340 if (without_array->block) {
1341 var->mode = vtn_variable_mode_ubo;
1342 b->shader->info.num_ubos++;
1343 } else if (without_array->buffer_block) {
1344 var->mode = vtn_variable_mode_ssbo;
1345 b->shader->info.num_ssbos++;
1346 } else if (glsl_type_is_image(without_array->type)) {
1347 var->mode = vtn_variable_mode_image;
1348 nir_mode = nir_var_uniform;
1349 b->shader->info.num_images++;
1350 } else if (glsl_type_is_sampler(without_array->type)) {
1351 var->mode = vtn_variable_mode_sampler;
1352 nir_mode = nir_var_uniform;
1353 b->shader->info.num_textures++;
1354 } else {
1355 assert(!"Invalid uniform variable type");
1356 }
1357 break;
1358 case SpvStorageClassPushConstant:
1359 var->mode = vtn_variable_mode_push_constant;
1360 assert(b->shader->num_uniforms == 0);
1361 b->shader->num_uniforms = vtn_type_block_size(var->type);
1362 break;
1363 case SpvStorageClassInput:
1364 var->mode = vtn_variable_mode_input;
1365 nir_mode = nir_var_shader_in;
1366 break;
1367 case SpvStorageClassOutput:
1368 var->mode = vtn_variable_mode_output;
1369 nir_mode = nir_var_shader_out;
1370 break;
1371 case SpvStorageClassPrivate:
1372 var->mode = vtn_variable_mode_global;
1373 nir_mode = nir_var_global;
1374 break;
1375 case SpvStorageClassFunction:
1376 var->mode = vtn_variable_mode_local;
1377 nir_mode = nir_var_local;
1378 break;
1379 case SpvStorageClassWorkgroup:
1380 var->mode = vtn_variable_mode_workgroup;
1381 nir_mode = nir_var_shared;
1382 break;
1383 case SpvStorageClassCrossWorkgroup:
1384 case SpvStorageClassGeneric:
1385 case SpvStorageClassAtomicCounter:
1386 default:
1387 unreachable("Unhandled variable storage class");
1388 }
1389
1390 switch (var->mode) {
1391 case vtn_variable_mode_local:
1392 case vtn_variable_mode_global:
1393 case vtn_variable_mode_image:
1394 case vtn_variable_mode_sampler:
1395 case vtn_variable_mode_workgroup:
1396 /* For these, we create the variable normally */
1397 var->var = rzalloc(b->shader, nir_variable);
1398 var->var->name = ralloc_strdup(var->var, val->name);
1399 var->var->type = var->type->type;
1400 var->var->data.mode = nir_mode;
1401
1402 switch (var->mode) {
1403 case vtn_variable_mode_image:
1404 case vtn_variable_mode_sampler:
1405 var->var->interface_type = without_array->type;
1406 break;
1407 default:
1408 var->var->interface_type = NULL;
1409 break;
1410 }
1411 break;
1412
1413 case vtn_variable_mode_input:
1414 case vtn_variable_mode_output: {
1415 /* In order to know whether or not we're a per-vertex inout, we need
1416 * the patch qualifier. This means walking the variable decorations
1417 * early before we actually create any variables. Not a big deal.
1418 *
1419 * GLSLang really likes to place decorations in the most interior
1420 * thing it possibly can. In particular, if you have a struct, it
1421 * will place the patch decorations on the struct members. This
1422 * should be handled by the variable splitting below just fine.
1423 *
1424 * If you have an array-of-struct, things get even more weird as it
1425 * will place the patch decorations on the struct even though it's
1426 * inside an array and some of the members being patch and others not
1427 * makes no sense whatsoever. Since the only sensible thing is for
1428 * it to be all or nothing, we'll call it patch if any of the members
1429 * are declared patch.
1430 */
1431 var->patch = false;
1432 vtn_foreach_decoration(b, val, var_is_patch_cb, &var->patch);
1433 if (glsl_type_is_array(var->type->type) &&
1434 glsl_type_is_struct(without_array->type)) {
1435 vtn_foreach_decoration(b, without_array->val,
1436 var_is_patch_cb, &var->patch);
1437 }
1438
1439 /* For inputs and outputs, we immediately split structures. This
1440 * is for a couple of reasons. For one, builtins may all come in
1441 * a struct and we really want those split out into separate
1442 * variables. For another, interpolation qualifiers can be
1443 * applied to members of the top-level struct ane we need to be
1444 * able to preserve that information.
1445 */
1446
1447 int array_length = -1;
1448 struct vtn_type *interface_type = var->type;
1449 if (is_per_vertex_inout(var, b->shader->stage)) {
1450 /* In Geometry shaders (and some tessellation), inputs come
1451 * in per-vertex arrays. However, some builtins come in
1452 * non-per-vertex, hence the need for the is_array check. In
1453 * any case, there are no non-builtin arrays allowed so this
1454 * check should be sufficient.
1455 */
1456 interface_type = var->type->array_element;
1457 array_length = glsl_get_length(var->type->type);
1458 }
1459
1460 if (glsl_type_is_struct(interface_type->type)) {
1461 /* It's a struct. Split it. */
1462 unsigned num_members = glsl_get_length(interface_type->type);
1463 var->members = ralloc_array(b, nir_variable *, num_members);
1464
1465 for (unsigned i = 0; i < num_members; i++) {
1466 const struct glsl_type *mtype = interface_type->members[i]->type;
1467 if (array_length >= 0)
1468 mtype = glsl_array_type(mtype, array_length);
1469
1470 var->members[i] = rzalloc(b->shader, nir_variable);
1471 var->members[i]->name =
1472 ralloc_asprintf(var->members[i], "%s.%d", val->name, i);
1473 var->members[i]->type = mtype;
1474 var->members[i]->interface_type =
1475 interface_type->members[i]->type;
1476 var->members[i]->data.mode = nir_mode;
1477 var->members[i]->data.patch = var->patch;
1478 }
1479 } else {
1480 var->var = rzalloc(b->shader, nir_variable);
1481 var->var->name = ralloc_strdup(var->var, val->name);
1482 var->var->type = var->type->type;
1483 var->var->interface_type = interface_type->type;
1484 var->var->data.mode = nir_mode;
1485 var->var->data.patch = var->patch;
1486 }
1487
1488 /* For inputs and outputs, we need to grab locations and builtin
1489 * information from the interface type.
1490 */
1491 vtn_foreach_decoration(b, interface_type->val, var_decoration_cb, var);
1492 break;
1493 }
1494
1495 case vtn_variable_mode_param:
1496 unreachable("Not created through OpVariable");
1497
1498 case vtn_variable_mode_ubo:
1499 case vtn_variable_mode_ssbo:
1500 case vtn_variable_mode_push_constant:
1501 /* These don't need actual variables. */
1502 break;
1503 }
1504
1505 if (count > 4) {
1506 assert(count == 5);
1507 nir_constant *constant =
1508 vtn_value(b, w[4], vtn_value_type_constant)->constant;
1509 var->var->constant_initializer =
1510 nir_constant_clone(constant, var->var);
1511 }
1512
1513 vtn_foreach_decoration(b, val, var_decoration_cb, var);
1514
1515 if (var->mode == vtn_variable_mode_image ||
1516 var->mode == vtn_variable_mode_sampler) {
1517 /* XXX: We still need the binding information in the nir_variable
1518 * for these. We should fix that.
1519 */
1520 var->var->data.binding = var->binding;
1521 var->var->data.descriptor_set = var->descriptor_set;
1522 var->var->data.index = var->input_attachment_index;
1523
1524 if (var->mode == vtn_variable_mode_image)
1525 var->var->data.image.format = without_array->image_format;
1526 }
1527
1528 if (var->mode == vtn_variable_mode_local) {
1529 assert(var->members == NULL && var->var != NULL);
1530 nir_function_impl_add_variable(b->impl, var->var);
1531 } else if (var->var) {
1532 nir_shader_add_variable(b->shader, var->var);
1533 } else if (var->members) {
1534 unsigned count = glsl_get_length(without_array->type);
1535 for (unsigned i = 0; i < count; i++) {
1536 assert(var->members[i]->data.mode != nir_var_local);
1537 nir_shader_add_variable(b->shader, var->members[i]);
1538 }
1539 } else {
1540 assert(var->mode == vtn_variable_mode_ubo ||
1541 var->mode == vtn_variable_mode_ssbo ||
1542 var->mode == vtn_variable_mode_push_constant);
1543 }
1544 break;
1545 }
1546
1547 case SpvOpAccessChain:
1548 case SpvOpInBoundsAccessChain: {
1549 struct vtn_access_chain *base, *chain;
1550 struct vtn_value *base_val = vtn_untyped_value(b, w[3]);
1551 if (base_val->value_type == vtn_value_type_sampled_image) {
1552 /* This is rather insane. SPIR-V allows you to use OpSampledImage
1553 * to combine an array of images with a single sampler to get an
1554 * array of sampled images that all share the same sampler.
1555 * Fortunately, this means that we can more-or-less ignore the
1556 * sampler when crawling the access chain, but it does leave us
1557 * with this rather awkward little special-case.
1558 */
1559 base = base_val->sampled_image->image;
1560 } else {
1561 assert(base_val->value_type == vtn_value_type_access_chain);
1562 base = base_val->access_chain;
1563 }
1564
1565 chain = vtn_access_chain_extend(b, base, count - 4);
1566
1567 unsigned idx = base->length;
1568 for (int i = 4; i < count; i++) {
1569 struct vtn_value *link_val = vtn_untyped_value(b, w[i]);
1570 if (link_val->value_type == vtn_value_type_constant) {
1571 chain->link[idx].mode = vtn_access_mode_literal;
1572 chain->link[idx].id = link_val->constant->values[0].u32[0];
1573 } else {
1574 chain->link[idx].mode = vtn_access_mode_id;
1575 chain->link[idx].id = w[i];
1576 }
1577 idx++;
1578 }
1579
1580 if (base_val->value_type == vtn_value_type_sampled_image) {
1581 struct vtn_value *val =
1582 vtn_push_value(b, w[2], vtn_value_type_sampled_image);
1583 val->sampled_image = ralloc(b, struct vtn_sampled_image);
1584 val->sampled_image->image = chain;
1585 val->sampled_image->sampler = base_val->sampled_image->sampler;
1586 } else {
1587 struct vtn_value *val =
1588 vtn_push_value(b, w[2], vtn_value_type_access_chain);
1589 val->access_chain = chain;
1590 }
1591 break;
1592 }
1593
1594 case SpvOpCopyMemory: {
1595 struct vtn_value *dest = vtn_value(b, w[1], vtn_value_type_access_chain);
1596 struct vtn_value *src = vtn_value(b, w[2], vtn_value_type_access_chain);
1597
1598 vtn_variable_copy(b, dest->access_chain, src->access_chain);
1599 break;
1600 }
1601
1602 case SpvOpLoad: {
1603 struct vtn_access_chain *src =
1604 vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
1605
1606 if (src->var->mode == vtn_variable_mode_image ||
1607 src->var->mode == vtn_variable_mode_sampler) {
1608 vtn_push_value(b, w[2], vtn_value_type_access_chain)->access_chain = src;
1609 return;
1610 }
1611
1612 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
1613 val->ssa = vtn_variable_load(b, src);
1614 break;
1615 }
1616
1617 case SpvOpStore: {
1618 struct vtn_access_chain *dest =
1619 vtn_value(b, w[1], vtn_value_type_access_chain)->access_chain;
1620
1621 if (glsl_type_is_sampler(dest->var->type->type)) {
1622 vtn_warn("OpStore of a sampler detected. Doing on-the-fly copy "
1623 "propagation to workaround the problem.");
1624 assert(dest->var->copy_prop_sampler == NULL);
1625 dest->var->copy_prop_sampler =
1626 vtn_value(b, w[2], vtn_value_type_access_chain)->access_chain;
1627 break;
1628 }
1629
1630 struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);
1631 vtn_variable_store(b, src, dest);
1632 break;
1633 }
1634
1635 case SpvOpArrayLength: {
1636 struct vtn_access_chain *chain =
1637 vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
1638
1639 const uint32_t offset = chain->var->type->offsets[w[4]];
1640 const uint32_t stride = chain->var->type->members[w[4]]->stride;
1641
1642 unsigned chain_idx;
1643 struct vtn_type *type;
1644 nir_ssa_def *index =
1645 get_vulkan_resource_index(b, chain, &type, &chain_idx);
1646
1647 nir_intrinsic_instr *instr =
1648 nir_intrinsic_instr_create(b->nb.shader,
1649 nir_intrinsic_get_buffer_size);
1650 instr->src[0] = nir_src_for_ssa(index);
1651 nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, NULL);
1652 nir_builder_instr_insert(&b->nb, &instr->instr);
1653 nir_ssa_def *buf_size = &instr->dest.ssa;
1654
1655 /* array_length = max(buffer_size - offset, 0) / stride */
1656 nir_ssa_def *array_length =
1657 nir_idiv(&b->nb,
1658 nir_imax(&b->nb,
1659 nir_isub(&b->nb,
1660 buf_size,
1661 nir_imm_int(&b->nb, offset)),
1662 nir_imm_int(&b->nb, 0u)),
1663 nir_imm_int(&b->nb, stride));
1664
1665 struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
1666 val->ssa = vtn_create_ssa_value(b, glsl_uint_type());
1667 val->ssa->def = array_length;
1668 break;
1669 }
1670
1671 case SpvOpCopyMemorySized:
1672 default:
1673 unreachable("Unhandled opcode");
1674 }
1675 }