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