xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2021 Collabora Ltd.
3  *
4  * Derived from tu_shader.c which is:
5  * Copyright © 2019 Google LLC
6  *
7  * Also derived from anv_pipeline.c which is
8  * Copyright © 2015 Intel Corporation
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice (including the next
18  * paragraph) shall be included in all copies or substantial portions of the
19  * Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */
29 
30 #include "panvk_device.h"
31 #include "panvk_shader.h"
32 
33 #include "vk_pipeline_layout.h"
34 
35 #include "util/bitset.h"
36 #include "nir.h"
37 #include "nir_builder.h"
38 
39 #if PAN_ARCH >= 9
40 #define VALHALL_RESOURCE_TABLE_IDX 62
41 #endif
42 
43 struct panvk_shader_desc_map {
44    /* The index of the map serves as the table offset, the value of the
45     * entry is a COPY_DESC_HANDLE() encoding the source set, and the
46     * index of the descriptor in the set. */
47    uint32_t *map;
48 
49    /* Number of entries in the map array. */
50    uint32_t count;
51 };
52 
53 struct panvk_shader_desc_info {
54    uint32_t used_set_mask;
55 #if PAN_ARCH <= 7
56    struct panvk_shader_desc_map dyn_ubos;
57    struct panvk_shader_desc_map dyn_ssbos;
58    struct panvk_shader_desc_map others[PANVK_BIFROST_DESC_TABLE_COUNT];
59 #else
60    uint32_t dummy_sampler_handle;
61    uint32_t dyn_bufs_start;
62    struct panvk_shader_desc_map dyn_bufs;
63 #endif
64 };
65 
66 struct lower_desc_ctx {
67    const struct panvk_descriptor_set_layout *set_layouts[MAX_SETS];
68    struct panvk_shader_desc_info desc_info;
69    struct hash_table *ht;
70    bool add_bounds_checks;
71    nir_address_format ubo_addr_format;
72    nir_address_format ssbo_addr_format;
73 };
74 
75 static nir_address_format
addr_format_for_desc_type(VkDescriptorType desc_type,const struct lower_desc_ctx * ctx)76 addr_format_for_desc_type(VkDescriptorType desc_type,
77                           const struct lower_desc_ctx *ctx)
78 {
79    switch (desc_type) {
80    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
81    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
82       return ctx->ubo_addr_format;
83 
84    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
85    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
86       return ctx->ssbo_addr_format;
87 
88    default:
89       unreachable("Unsupported descriptor type");
90    }
91 }
92 
93 static const struct panvk_descriptor_set_layout *
get_set_layout(uint32_t set,const struct lower_desc_ctx * ctx)94 get_set_layout(uint32_t set, const struct lower_desc_ctx *ctx)
95 {
96    return ctx->set_layouts[set];
97 }
98 
99 static const struct panvk_descriptor_set_binding_layout *
get_binding_layout(uint32_t set,uint32_t binding,const struct lower_desc_ctx * ctx)100 get_binding_layout(uint32_t set, uint32_t binding,
101                    const struct lower_desc_ctx *ctx)
102 {
103    return &get_set_layout(set, ctx)->bindings[binding];
104 }
105 
106 #define DELETED_KEY (void *)(uintptr_t)1
107 
108 struct desc_id {
109    uint32_t set;
110    uint32_t binding;
111    uint32_t subdesc;
112 };
113 
114 static void *
desc_id_to_key(struct desc_id id)115 desc_id_to_key(struct desc_id id)
116 {
117    assert(id.set <= BITFIELD_MASK(4));
118    assert(id.subdesc <= BITFIELD_MASK(1));
119    assert(id.binding <= BITFIELD_MASK(27));
120 
121    uint32_t handle = (id.set << 28) | (id.subdesc << 27) | id.binding;
122    assert(handle < UINT32_MAX - 2);
123    return (void *)(uintptr_t)(handle + 2);
124 }
125 
126 static struct desc_id
key_to_desc_id(const void * key)127 key_to_desc_id(const void *key)
128 {
129    uint32_t handle = (uintptr_t)key - 2;
130 
131    return (struct desc_id){
132       .set = handle >> 28,
133       .subdesc = (handle & BITFIELD_BIT(27)) ? 1 : 0,
134       .binding = handle & BITFIELD_MASK(27),
135    };
136 }
137 
138 #if PAN_ARCH <= 7
139 static enum panvk_bifrost_desc_table_type
desc_type_to_table_type(VkDescriptorType type,unsigned subdesc_idx)140 desc_type_to_table_type(VkDescriptorType type, unsigned subdesc_idx)
141 {
142    switch (type) {
143    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
144       return subdesc_idx == 1 ? PANVK_BIFROST_DESC_TABLE_SAMPLER
145                               : PANVK_BIFROST_DESC_TABLE_TEXTURE;
146    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
147    case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
148    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
149       return PANVK_BIFROST_DESC_TABLE_TEXTURE;
150    case VK_DESCRIPTOR_TYPE_SAMPLER:
151       return PANVK_BIFROST_DESC_TABLE_SAMPLER;
152    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
153    case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
154       return PANVK_BIFROST_DESC_TABLE_IMG;
155    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
156       return PANVK_BIFROST_DESC_TABLE_UBO;
157    default:
158       return PANVK_BIFROST_DESC_TABLE_INVALID;
159    }
160 }
161 #endif
162 
163 static uint32_t
get_subdesc_idx(const struct panvk_descriptor_set_binding_layout * bind_layout,VkDescriptorType subdesc_type)164 get_subdesc_idx(const struct panvk_descriptor_set_binding_layout *bind_layout,
165                 VkDescriptorType subdesc_type)
166 {
167    if (bind_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
168       assert(subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
169              subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLER);
170       return subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLER ? 1 : 0;
171    }
172 
173    return 0;
174 }
175 
176 static uint32_t
shader_desc_idx(uint32_t set,uint32_t binding,VkDescriptorType subdesc_type,const struct lower_desc_ctx * ctx)177 shader_desc_idx(uint32_t set, uint32_t binding, VkDescriptorType subdesc_type,
178                 const struct lower_desc_ctx *ctx)
179 {
180    const struct panvk_descriptor_set_layout *set_layout =
181       get_set_layout(set, ctx);
182    const struct panvk_descriptor_set_binding_layout *bind_layout =
183       &set_layout->bindings[binding];
184    uint32_t subdesc_idx = get_subdesc_idx(bind_layout, subdesc_type);
185 
186    /* On Valhall, all non-dynamic descriptors are accessed directly through
187     * their set. The vertex attribute table always comes first, so we always
188     * offset user sets by one if we're dealing with a vertex shader. */
189    if (PAN_ARCH >= 9 &&
190        bind_layout->type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC &&
191        bind_layout->type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
192       return pan_res_handle(set + 1, bind_layout->desc_idx + subdesc_idx);
193 
194    /* On Bifrost, the SSBO descriptors are read directly from the set. */
195    if (PAN_ARCH <= 7 && bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
196       return bind_layout->desc_idx;
197 
198    struct desc_id src = {
199       .set = set,
200       .subdesc = subdesc_idx,
201       .binding = binding,
202    };
203    struct hash_entry *he =
204       _mesa_hash_table_search(ctx->ht, desc_id_to_key(src));
205 
206    assert(he);
207 
208    const struct panvk_shader_desc_map *map;
209    uint32_t *entry = he->data;
210 
211 #if PAN_ARCH <= 7
212    if (bind_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
213       map = &ctx->desc_info.dyn_ubos;
214    } else if (bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
215       map = &ctx->desc_info.dyn_ssbos;
216    } else {
217       uint32_t table = desc_type_to_table_type(bind_layout->type, src.subdesc);
218 
219       assert(table < PANVK_BIFROST_DESC_TABLE_COUNT);
220       map = &ctx->desc_info.others[table];
221    }
222 #else
223    map = &ctx->desc_info.dyn_bufs;
224 #endif
225 
226    assert(entry >= map->map && entry < map->map + map->count);
227 
228    uint32_t idx = entry - map->map;
229 
230 #if PAN_ARCH <= 7
231    /* Adjust the destination index for all dynamic UBOs, which are laid out
232     * just after the regular UBOs in the UBO table. */
233    if (bind_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
234       idx += ctx->desc_info.others[PANVK_BIFROST_DESC_TABLE_UBO].count;
235 #else
236    /* Dynamic buffers are pushed directly in the resource tables, after all
237     * sets. */
238    idx = pan_res_handle(0, ctx->desc_info.dyn_bufs_start + idx);
239 #endif
240 
241    return idx;
242 }
243 
244 static nir_address_format
addr_format_for_type(VkDescriptorType type,const struct lower_desc_ctx * ctx)245 addr_format_for_type(VkDescriptorType type, const struct lower_desc_ctx *ctx)
246 {
247    switch (type) {
248    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
249    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
250       return ctx->ubo_addr_format;
251 
252    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
253    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
254       return ctx->ssbo_addr_format;
255 
256    default:
257       unreachable("Unsupported descriptor type");
258       return ~0;
259    }
260 }
261 
262 #if PAN_ARCH <= 7
263 static uint32_t
shader_ssbo_table(nir_builder * b,unsigned set,unsigned binding,const struct lower_desc_ctx * ctx)264 shader_ssbo_table(nir_builder *b, unsigned set, unsigned binding,
265                   const struct lower_desc_ctx *ctx)
266 {
267    const struct panvk_descriptor_set_layout *set_layout =
268       get_set_layout(set, ctx);
269    const struct panvk_descriptor_set_binding_layout *bind_layout =
270       &set_layout->bindings[binding];
271 
272    assert(bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
273           bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
274    bool is_dyn = bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
275 
276    if (b->shader->info.stage == MESA_SHADER_COMPUTE)
277       return !is_dyn ? offsetof(struct panvk_compute_sysvals, desc.sets[set])
278                      : offsetof(struct panvk_compute_sysvals, desc.dyn_ssbos);
279    else if (b->shader->info.stage == MESA_SHADER_VERTEX)
280       return !is_dyn
281                 ? offsetof(struct panvk_graphics_sysvals, desc.sets[set])
282                 : offsetof(struct panvk_graphics_sysvals, desc.vs_dyn_ssbos);
283    else
284       return !is_dyn
285                 ? offsetof(struct panvk_graphics_sysvals, desc.sets[set])
286                 : offsetof(struct panvk_graphics_sysvals, desc.fs_dyn_ssbos);
287 }
288 #endif
289 
290 /** Build a Vulkan resource index
291  *
292  * A "resource index" is the term used by our SPIR-V parser and the relevant
293  * NIR intrinsics for a reference into a descriptor set.  It acts much like a
294  * deref in NIR except that it accesses opaque descriptors instead of memory.
295  *
296  * Coming out of SPIR-V, both the resource indices (in the form of
297  * vulkan_resource_[re]index intrinsics) and the memory derefs (in the form
298  * of nir_deref_instr) use the same vector component/bit size.  The meaning
299  * of those values for memory derefs (nir_deref_instr) is given by the
300  * nir_address_format associated with the descriptor type.  For resource
301  * indices, it's an entirely internal to panvk encoding which describes, in
302  * some sense, the address of the descriptor.  Thanks to the NIR/SPIR-V rules,
303  * it must be packed into the same size SSA values as a memory address.  For
304  * this reason, the actual encoding may depend both on the address format for
305  * memory derefs and the descriptor address format.
306  *
307  * The load_vulkan_descriptor intrinsic exists to provide a transition point
308  * between these two forms of derefs: descriptor and memory.
309  */
310 static nir_def *
build_res_index(nir_builder * b,uint32_t set,uint32_t binding,nir_def * array_index,nir_address_format addr_format,const struct lower_desc_ctx * ctx)311 build_res_index(nir_builder *b, uint32_t set, uint32_t binding,
312                 nir_def *array_index, nir_address_format addr_format,
313                 const struct lower_desc_ctx *ctx)
314 {
315    const struct panvk_descriptor_set_layout *set_layout =
316       get_set_layout(set, ctx);
317    const struct panvk_descriptor_set_binding_layout *bind_layout =
318       &set_layout->bindings[binding];
319    uint32_t array_size = bind_layout->desc_count;
320    nir_address_format addr_fmt = addr_format_for_type(bind_layout->type, ctx);
321    uint32_t desc_idx = shader_desc_idx(set, binding, bind_layout->type, ctx);
322 
323    switch (addr_fmt) {
324 #if PAN_ARCH <= 7
325    case nir_address_format_32bit_index_offset: {
326       const uint32_t packed_desc_idx_array_size =
327          (array_size - 1) << 16 | desc_idx;
328 
329       return nir_vec2(b, nir_imm_int(b, packed_desc_idx_array_size),
330                       array_index);
331    }
332 
333    case nir_address_format_64bit_bounded_global:
334    case nir_address_format_64bit_global_32bit_offset: {
335       unsigned base_addr_sysval_offs = shader_ssbo_table(b, set, binding, ctx);
336 
337       return nir_vec4(b, nir_imm_int(b, base_addr_sysval_offs),
338                       nir_imm_int(b, desc_idx), array_index,
339                       nir_imm_int(b, array_size - 1));
340    }
341 #else
342    case nir_address_format_vec2_index_32bit_offset:
343       return nir_vec3(b, nir_imm_int(b, desc_idx), array_index,
344                       nir_imm_int(b, array_size - 1));
345 #endif
346 
347    default:
348       unreachable("Unsupported descriptor type");
349    }
350 }
351 
352 /** Adjust a Vulkan resource index
353  *
354  * This is the equivalent of nir_deref_type_ptr_as_array for resource indices.
355  * For array descriptors, it allows us to adjust the array index.  Thanks to
356  * variable pointers, we cannot always fold this re-index operation into the
357  * vulkan_resource_index intrinsic and we have to do it based on nothing but
358  * the address format.
359  */
360 static nir_def *
build_res_reindex(nir_builder * b,nir_def * orig,nir_def * delta,nir_address_format addr_format)361 build_res_reindex(nir_builder *b, nir_def *orig, nir_def *delta,
362                   nir_address_format addr_format)
363 {
364    switch (addr_format) {
365 #if PAN_ARCH <= 7
366    case nir_address_format_32bit_index_offset:
367       return nir_vec2(b, nir_channel(b, orig, 0),
368                       nir_iadd(b, nir_channel(b, orig, 1), delta));
369 
370    case nir_address_format_64bit_bounded_global:
371    case nir_address_format_64bit_global_32bit_offset:
372       return nir_vec4(b, nir_channel(b, orig, 0), nir_channel(b, orig, 1),
373                       nir_iadd(b, nir_channel(b, orig, 2), delta),
374                       nir_imm_int(b, 3));
375 #else
376    case nir_address_format_vec2_index_32bit_offset:
377       return nir_vec3(b, nir_channel(b, orig, 0),
378                       nir_iadd(b, nir_channel(b, orig, 1), delta),
379                       nir_channel(b, orig, 2));
380 #endif
381 
382    default:
383       unreachable("Unhandled address format");
384    }
385 }
386 
387 /** Convert a Vulkan resource index into a buffer address
388  *
389  * In some cases, this does a  memory load from the descriptor set and, in
390  * others, it simply converts from one form to another.
391  *
392  * See build_res_index for details about each resource index format.
393  */
394 static nir_def *
build_buffer_addr_for_res_index(nir_builder * b,nir_def * res_index,nir_address_format addr_format,const struct lower_desc_ctx * ctx)395 build_buffer_addr_for_res_index(nir_builder *b, nir_def *res_index,
396                                 nir_address_format addr_format,
397                                 const struct lower_desc_ctx *ctx)
398 {
399    switch (addr_format) {
400 #if PAN_ARCH <= 7
401    case nir_address_format_32bit_index_offset: {
402       nir_def *packed = nir_channel(b, res_index, 0);
403       nir_def *array_index = nir_channel(b, res_index, 1);
404       nir_def *first_desc_index = nir_extract_u16(b, packed, nir_imm_int(b, 0));
405       nir_def *array_max = nir_extract_u16(b, packed, nir_imm_int(b, 1));
406 
407       if (ctx->add_bounds_checks)
408          array_index = nir_umin(b, array_index, array_max);
409 
410       return nir_vec2(b, nir_iadd(b, first_desc_index, array_index),
411                       nir_imm_int(b, 0));
412    }
413 
414    case nir_address_format_64bit_bounded_global:
415    case nir_address_format_64bit_global_32bit_offset: {
416       nir_def *base_addr_sysval_offset = nir_channel(b, res_index, 0);
417       nir_def *first_desc_index = nir_channel(b, res_index, 1);
418       nir_def *array_index = nir_channel(b, res_index, 2);
419       nir_def *array_max = nir_channel(b, res_index, 3);
420 
421       if (ctx->add_bounds_checks)
422          array_index = nir_umin(b, array_index, array_max);
423 
424       nir_def *desc_offset = nir_imul_imm(
425          b, nir_iadd(b, array_index, first_desc_index), PANVK_DESCRIPTOR_SIZE);
426 
427       nir_def *base_addr = nir_load_push_constant(
428          b, 1, 64, base_addr_sysval_offset, .base = 256, .range = 256);
429       nir_def *desc_addr = nir_iadd(b, base_addr, nir_u2u64(b, desc_offset));
430       nir_def *desc =
431          nir_load_global(b, desc_addr, PANVK_DESCRIPTOR_SIZE, 4, 32);
432 
433       /* The offset in the descriptor is guaranteed to be zero when it's
434        * written into the descriptor set.  This lets us avoid some unnecessary
435        * adds.
436        */
437       return nir_vec4(b, nir_channel(b, desc, 0), nir_channel(b, desc, 1),
438                       nir_channel(b, desc, 2), nir_imm_int(b, 0));
439    }
440 #else
441    case nir_address_format_vec2_index_32bit_offset: {
442       nir_def *first_desc_index = nir_channel(b, res_index, 0);
443       nir_def *array_index = nir_channel(b, res_index, 1);
444       nir_def *array_max = nir_channel(b, res_index, 2);
445 
446       if (ctx->add_bounds_checks)
447          array_index = nir_umin(b, array_index, array_max);
448 
449       return nir_vec3(b, first_desc_index, array_index, nir_imm_int(b, 0));
450    }
451 #endif
452 
453    default:
454       unreachable("Unhandled address format");
455    }
456 }
457 
458 static bool
lower_res_intrinsic(nir_builder * b,nir_intrinsic_instr * intrin,const struct lower_desc_ctx * ctx)459 lower_res_intrinsic(nir_builder *b, nir_intrinsic_instr *intrin,
460                     const struct lower_desc_ctx *ctx)
461 {
462    b->cursor = nir_before_instr(&intrin->instr);
463 
464    const VkDescriptorType desc_type = nir_intrinsic_desc_type(intrin);
465    nir_address_format addr_format = addr_format_for_desc_type(desc_type, ctx);
466 
467    nir_def *res;
468    switch (intrin->intrinsic) {
469    case nir_intrinsic_vulkan_resource_index:
470       res = build_res_index(b, nir_intrinsic_desc_set(intrin),
471                             nir_intrinsic_binding(intrin), intrin->src[0].ssa,
472                             addr_format, ctx);
473       break;
474 
475    case nir_intrinsic_vulkan_resource_reindex:
476       res = build_res_reindex(b, intrin->src[0].ssa, intrin->src[1].ssa,
477                               addr_format);
478       break;
479 
480    case nir_intrinsic_load_vulkan_descriptor:
481       res = build_buffer_addr_for_res_index(b, intrin->src[0].ssa, addr_format,
482                                             ctx);
483       break;
484 
485    default:
486       unreachable("Unhandled resource intrinsic");
487    }
488 
489    assert(intrin->def.bit_size == res->bit_size);
490    assert(intrin->def.num_components == res->num_components);
491    nir_def_replace(&intrin->def, res);
492 
493    return true;
494 }
495 
496 static void
get_resource_deref_binding(nir_deref_instr * deref,uint32_t * set,uint32_t * binding,uint32_t * index_imm,nir_def ** index_ssa,uint32_t * max_idx)497 get_resource_deref_binding(nir_deref_instr *deref, uint32_t *set,
498                            uint32_t *binding, uint32_t *index_imm,
499                            nir_def **index_ssa, uint32_t *max_idx)
500 {
501    *index_imm = 0;
502    *max_idx = 0;
503    *index_ssa = NULL;
504 
505    if (deref->deref_type == nir_deref_type_array) {
506       if (nir_src_is_const(deref->arr.index)) {
507          *index_imm = nir_src_as_uint(deref->arr.index);
508          *max_idx = *index_imm;
509       } else {
510          *index_ssa = deref->arr.index.ssa;
511 
512          /* Zero means variable array. The minus one should give us UINT32_MAX,
513           * which matches what we want. */
514          *max_idx = glsl_array_size(nir_deref_instr_parent(deref)->type) - 1;
515       }
516 
517       deref = nir_deref_instr_parent(deref);
518    }
519 
520    assert(deref->deref_type == nir_deref_type_var);
521    nir_variable *var = deref->var;
522 
523    *set = var->data.descriptor_set;
524    *binding = var->data.binding;
525 }
526 
527 static nir_def *
load_resource_deref_desc(nir_builder * b,nir_deref_instr * deref,VkDescriptorType subdesc_type,unsigned desc_offset,unsigned num_components,unsigned bit_size,const struct lower_desc_ctx * ctx)528 load_resource_deref_desc(nir_builder *b, nir_deref_instr *deref,
529                          VkDescriptorType subdesc_type, unsigned desc_offset,
530                          unsigned num_components, unsigned bit_size,
531                          const struct lower_desc_ctx *ctx)
532 {
533    uint32_t set, binding, index_imm, max_idx;
534    nir_def *index_ssa;
535    get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
536                               &max_idx);
537 
538    const struct panvk_descriptor_set_layout *set_layout =
539       get_set_layout(set, ctx);
540    const struct panvk_descriptor_set_binding_layout *bind_layout =
541       &set_layout->bindings[binding];
542    unsigned subdesc_idx = get_subdesc_idx(bind_layout, subdesc_type);
543 
544    assert(index_ssa == NULL || index_imm == 0);
545    if (index_ssa == NULL)
546       index_ssa = nir_imm_int(b, index_imm);
547 
548    unsigned desc_stride = panvk_get_desc_stride(bind_layout->type);
549    nir_def *set_offset =
550       nir_imul_imm(b,
551                    nir_iadd_imm(b, nir_imul_imm(b, index_ssa, desc_stride),
552                                 bind_layout->desc_idx + subdesc_idx),
553                    PANVK_DESCRIPTOR_SIZE);
554 
555    set_offset = nir_iadd_imm(b, set_offset, desc_offset);
556 
557 #if PAN_ARCH <= 7
558    unsigned set_base_addr_sysval_offs =
559       b->shader->info.stage == MESA_SHADER_COMPUTE
560          ? offsetof(struct panvk_compute_sysvals, desc.sets[set])
561          : offsetof(struct panvk_graphics_sysvals, desc.sets[set]);
562    nir_def *set_base_addr = nir_load_push_constant(
563       b, 1, 64, nir_imm_int(b, 0), .base = 256 + set_base_addr_sysval_offs,
564       .range = 8);
565 
566    unsigned desc_align = 1 << (ffs(PANVK_DESCRIPTOR_SIZE + desc_offset) - 1);
567 
568    return nir_load_global(b,
569                           nir_iadd(b, set_base_addr, nir_u2u64(b, set_offset)),
570                           desc_align, num_components, bit_size);
571 #else
572    return nir_load_ubo(
573       b, num_components, bit_size,
574       nir_imm_int(b, pan_res_handle(VALHALL_RESOURCE_TABLE_IDX, set)),
575       set_offset, .range = ~0u, .align_mul = PANVK_DESCRIPTOR_SIZE,
576       .align_offset = desc_offset);
577 #endif
578 }
579 
580 static nir_def *
load_tex_size(nir_builder * b,nir_deref_instr * deref,enum glsl_sampler_dim dim,bool is_array,const struct lower_desc_ctx * ctx)581 load_tex_size(nir_builder *b, nir_deref_instr *deref, enum glsl_sampler_dim dim,
582               bool is_array, const struct lower_desc_ctx *ctx)
583 {
584    if (dim == GLSL_SAMPLER_DIM_BUF) {
585       nir_def *tex_w = load_resource_deref_desc(
586          b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 4, 1, 16, ctx);
587 
588       /* S dimension is 16 bits wide. We don't support combining S,T dimensions
589        * to allow large buffers yet. */
590       return nir_iadd_imm(b, nir_u2u32(b, tex_w), 1);
591    } else {
592       nir_def *tex_w_h = load_resource_deref_desc(
593          b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 4, 2, 16, ctx);
594       nir_def *tex_depth_or_layer_count = load_resource_deref_desc(
595          b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
596          dim == GLSL_SAMPLER_DIM_3D ? 28 : 24, 1, 16, ctx);
597 
598       nir_def *tex_sz =
599          is_array && dim == GLSL_SAMPLER_DIM_1D
600             ? nir_vec2(b, nir_channel(b, tex_w_h, 0), tex_depth_or_layer_count)
601             : nir_vec3(b, nir_channel(b, tex_w_h, 0),
602                        nir_channel(b, tex_w_h, 1), tex_depth_or_layer_count);
603 
604       tex_sz = nir_pad_vector_imm_int(b, tex_sz, 0, 4);
605 
606       /* The sizes are provided as 16-bit values with 1 subtracted so
607        * convert to 32-bit and add 1.
608        */
609       return nir_iadd_imm(b, nir_u2u32(b, tex_sz), 1);
610    }
611 }
612 
613 static nir_def *
load_img_size(nir_builder * b,nir_deref_instr * deref,enum glsl_sampler_dim dim,bool is_array,const struct lower_desc_ctx * ctx)614 load_img_size(nir_builder *b, nir_deref_instr *deref, enum glsl_sampler_dim dim,
615               bool is_array, const struct lower_desc_ctx *ctx)
616 {
617    if (PAN_ARCH >= 9)
618       return load_tex_size(b, deref, dim, is_array, ctx);
619 
620    if (dim == GLSL_SAMPLER_DIM_BUF) {
621       nir_def *tex_w = load_resource_deref_desc(
622          b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 18, 1, 16, ctx);
623 
624       /* S dimension is 16 bits wide. We don't support combining S,T dimensions
625        * to allow large buffers yet. */
626       return nir_iadd_imm(b, nir_u2u32(b, tex_w), 1);
627    } else {
628       nir_def *tex_sz = load_resource_deref_desc(
629          b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 18, 3, 16, ctx);
630 
631       if (is_array && dim == GLSL_SAMPLER_DIM_1D)
632          tex_sz =
633             nir_vec2(b, nir_channel(b, tex_sz, 0), nir_channel(b, tex_sz, 2));
634 
635       tex_sz = nir_pad_vector_imm_int(b, tex_sz, 0, 4);
636 
637       /* The sizes are provided as 16-bit values with 1 subtracted so
638        * convert to 32-bit and add 1.
639        */
640       return nir_iadd_imm(b, nir_u2u32(b, tex_sz), 1);
641    }
642 }
643 
644 static nir_def *
load_tex_levels(nir_builder * b,nir_deref_instr * deref,enum glsl_sampler_dim dim,const struct lower_desc_ctx * ctx)645 load_tex_levels(nir_builder *b, nir_deref_instr *deref,
646                 enum glsl_sampler_dim dim, const struct lower_desc_ctx *ctx)
647 {
648    assert(dim != GLSL_SAMPLER_DIM_BUF);
649 
650    /* LOD count is stored in word2[16:21] and has a minus(1) modifier. */
651    nir_def *tex_word2 = load_resource_deref_desc(
652       b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 8, 1, 32, ctx);
653    nir_def *lod_count = nir_iand_imm(b, nir_ushr_imm(b, tex_word2, 16), 0x1f);
654    return nir_iadd_imm(b, lod_count, 1);
655 }
656 
657 static nir_def *
load_tex_samples(nir_builder * b,nir_deref_instr * deref,enum glsl_sampler_dim dim,const struct lower_desc_ctx * ctx)658 load_tex_samples(nir_builder *b, nir_deref_instr *deref,
659                  enum glsl_sampler_dim dim, const struct lower_desc_ctx *ctx)
660 {
661    assert(dim != GLSL_SAMPLER_DIM_BUF);
662 
663    /* Sample count is stored in word3[13:25], and has a log2 modifier. */
664    nir_def *tex_word3 = load_resource_deref_desc(
665       b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 12, 1, 32, ctx);
666    nir_def *sample_count = nir_iand_imm(b, nir_ushr_imm(b, tex_word3, 13), 0x7);
667    return nir_ishl(b, nir_imm_int(b, 1), sample_count);
668 }
669 
670 static nir_def *
load_img_samples(nir_builder * b,nir_deref_instr * deref,enum glsl_sampler_dim dim,const struct lower_desc_ctx * ctx)671 load_img_samples(nir_builder *b, nir_deref_instr *deref,
672                  enum glsl_sampler_dim dim, const struct lower_desc_ctx *ctx)
673 {
674    if (PAN_ARCH >= 9)
675       return load_tex_samples(b, deref, dim, ctx);
676 
677    assert(dim != GLSL_SAMPLER_DIM_BUF);
678 
679    /* Sample count is stored in the image depth field.
680     * FIXME: This won't work for 2DMSArray images, but those are already
681     * broken. */
682    nir_def *sample_count = load_resource_deref_desc(
683       b, deref, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 22, 1, 16, ctx);
684    return nir_iadd_imm(b, nir_u2u32(b, sample_count), 1);
685 }
686 
687 static bool
lower_tex(nir_builder * b,nir_tex_instr * tex,const struct lower_desc_ctx * ctx)688 lower_tex(nir_builder *b, nir_tex_instr *tex, const struct lower_desc_ctx *ctx)
689 {
690    bool progress = false;
691 
692    b->cursor = nir_before_instr(&tex->instr);
693 
694    if (tex->op == nir_texop_txs || tex->op == nir_texop_query_levels ||
695        tex->op == nir_texop_texture_samples) {
696       int tex_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
697       assert(tex_src_idx >= 0);
698       nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_src_idx].src);
699 
700       const enum glsl_sampler_dim dim = tex->sampler_dim;
701 
702       nir_def *res;
703       switch (tex->op) {
704       case nir_texop_txs:
705          res = nir_channels(b, load_tex_size(b, deref, dim, tex->is_array, ctx),
706                             nir_component_mask(tex->def.num_components));
707          break;
708       case nir_texop_query_levels:
709          assert(tex->def.num_components == 1);
710          res = load_tex_levels(b, deref, dim, ctx);
711          break;
712       case nir_texop_texture_samples:
713          assert(tex->def.num_components == 1);
714          res = load_tex_samples(b, deref, dim, ctx);
715          break;
716       default:
717          unreachable("Unsupported texture query op");
718       }
719 
720       nir_def_replace(&tex->def, res);
721       return true;
722    }
723 
724    int sampler_src_idx =
725       nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
726    if (sampler_src_idx >= 0) {
727       nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src);
728       nir_tex_instr_remove_src(tex, sampler_src_idx);
729 
730       uint32_t set, binding, index_imm, max_idx;
731       nir_def *index_ssa;
732       get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
733                                  &max_idx);
734 
735       tex->sampler_index =
736          shader_desc_idx(set, binding, VK_DESCRIPTOR_TYPE_SAMPLER, ctx) +
737          index_imm;
738 
739       if (index_ssa != NULL) {
740          nir_tex_instr_add_src(tex, nir_tex_src_sampler_offset, index_ssa);
741       }
742       progress = true;
743    } else {
744 #if PAN_ARCH >= 9
745       tex->sampler_index = ctx->desc_info.dummy_sampler_handle;
746 #endif
747    }
748 
749    int tex_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
750    if (tex_src_idx >= 0) {
751       nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_src_idx].src);
752       nir_tex_instr_remove_src(tex, tex_src_idx);
753 
754       uint32_t set, binding, index_imm, max_idx;
755       nir_def *index_ssa;
756       get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
757                                  &max_idx);
758 
759       tex->texture_index =
760          shader_desc_idx(set, binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, ctx) +
761          index_imm;
762 
763       if (index_ssa != NULL) {
764          nir_tex_instr_add_src(tex, nir_tex_src_texture_offset, index_ssa);
765       }
766       progress = true;
767    }
768 
769    return progress;
770 }
771 
772 static nir_def *
get_img_index(nir_builder * b,nir_deref_instr * deref,const struct lower_desc_ctx * ctx)773 get_img_index(nir_builder *b, nir_deref_instr *deref,
774               const struct lower_desc_ctx *ctx)
775 {
776    uint32_t set, binding, index_imm, max_idx;
777    nir_def *index_ssa;
778    get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
779                               &max_idx);
780 
781    const struct panvk_descriptor_set_binding_layout *bind_layout =
782       get_binding_layout(set, binding, ctx);
783    assert(bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
784           bind_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
785           bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
786 
787    unsigned img_offset = shader_desc_idx(set, binding, bind_layout->type, ctx);
788 
789    if (index_ssa == NULL) {
790       return nir_imm_int(b, img_offset + index_imm);
791    } else {
792       assert(index_imm == 0);
793       return nir_iadd_imm(b, index_ssa, img_offset);
794    }
795 }
796 
797 static bool
lower_img_intrinsic(nir_builder * b,nir_intrinsic_instr * intr,struct lower_desc_ctx * ctx)798 lower_img_intrinsic(nir_builder *b, nir_intrinsic_instr *intr,
799                     struct lower_desc_ctx *ctx)
800 {
801    b->cursor = nir_before_instr(&intr->instr);
802    nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
803 
804    if (intr->intrinsic == nir_intrinsic_image_deref_size ||
805        intr->intrinsic == nir_intrinsic_image_deref_samples) {
806       const enum glsl_sampler_dim dim = nir_intrinsic_image_dim(intr);
807       bool is_array = nir_intrinsic_image_array(intr);
808 
809       nir_def *res;
810       switch (intr->intrinsic) {
811       case nir_intrinsic_image_deref_size:
812          res = nir_channels(b, load_img_size(b, deref, dim, is_array, ctx),
813                             nir_component_mask(intr->def.num_components));
814          break;
815       case nir_intrinsic_image_deref_samples:
816          res = load_img_samples(b, deref, dim, ctx);
817          break;
818       default:
819          unreachable("Unsupported image query op");
820       }
821 
822       nir_def_replace(&intr->def, res);
823    } else {
824       nir_rewrite_image_intrinsic(intr, get_img_index(b, deref, ctx), false);
825    }
826 
827    return true;
828 }
829 
830 static bool
lower_intrinsic(nir_builder * b,nir_intrinsic_instr * intr,struct lower_desc_ctx * ctx)831 lower_intrinsic(nir_builder *b, nir_intrinsic_instr *intr,
832                 struct lower_desc_ctx *ctx)
833 {
834    switch (intr->intrinsic) {
835    case nir_intrinsic_vulkan_resource_index:
836    case nir_intrinsic_vulkan_resource_reindex:
837    case nir_intrinsic_load_vulkan_descriptor:
838       return lower_res_intrinsic(b, intr, ctx);
839    case nir_intrinsic_image_deref_store:
840    case nir_intrinsic_image_deref_load:
841    case nir_intrinsic_image_deref_atomic:
842    case nir_intrinsic_image_deref_atomic_swap:
843    case nir_intrinsic_image_deref_size:
844    case nir_intrinsic_image_deref_samples:
845       return lower_img_intrinsic(b, intr, ctx);
846    default:
847       return false;
848    }
849 }
850 
851 static bool
lower_descriptors_instr(nir_builder * b,nir_instr * instr,void * data)852 lower_descriptors_instr(nir_builder *b, nir_instr *instr, void *data)
853 {
854    struct lower_desc_ctx *ctx = data;
855 
856    switch (instr->type) {
857    case nir_instr_type_tex:
858       return lower_tex(b, nir_instr_as_tex(instr), ctx);
859    case nir_instr_type_intrinsic:
860       return lower_intrinsic(b, nir_instr_as_intrinsic(instr), ctx);
861    default:
862       return false;
863    }
864 }
865 
866 static void
record_binding(struct lower_desc_ctx * ctx,unsigned set,unsigned binding,VkDescriptorType subdesc_type,uint32_t max_idx)867 record_binding(struct lower_desc_ctx *ctx, unsigned set, unsigned binding,
868                VkDescriptorType subdesc_type, uint32_t max_idx)
869 {
870    const struct panvk_descriptor_set_layout *set_layout = ctx->set_layouts[set];
871    const struct panvk_descriptor_set_binding_layout *binding_layout =
872       &set_layout->bindings[binding];
873    uint32_t subdesc_idx = get_subdesc_idx(binding_layout, subdesc_type);
874    uint32_t desc_stride = panvk_get_desc_stride(binding_layout->type);
875 
876    assert(desc_stride == 1 || desc_stride == 2);
877    ctx->desc_info.used_set_mask |= BITFIELD_BIT(set);
878 
879    /* On valhall, we only record dynamic bindings, others are accessed directly
880     * from the set. */
881    if (PAN_ARCH >= 9 &&
882        binding_layout->type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC &&
883        binding_layout->type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
884       return;
885 
886    /* SSBOs are accessed directly from the sets, no need to record accesses
887     * to such resources. */
888    if (PAN_ARCH <= 7 &&
889        binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
890       return;
891 
892    assert(subdesc_idx < desc_stride);
893    assert(!(binding & BITFIELD_BIT(27)));
894 
895    struct desc_id src = {
896       .set = set,
897       .subdesc = subdesc_idx,
898       .binding = binding,
899    };
900    const void *key = desc_id_to_key(src);
901    struct hash_entry *he = _mesa_hash_table_search(ctx->ht, key);
902    uint32_t old_desc_count = 0;
903    uint32_t new_desc_count =
904       max_idx == UINT32_MAX ? binding_layout->desc_count : max_idx + 1;
905 
906    assert(new_desc_count <= binding_layout->desc_count);
907 
908    if (!he)
909       he = _mesa_hash_table_insert(ctx->ht, key,
910                                    (void *)(uintptr_t)new_desc_count);
911    else
912       old_desc_count = (uintptr_t)he->data;
913 
914    if (old_desc_count >= new_desc_count)
915       return;
916 
917    uint32_t desc_count_diff = new_desc_count - old_desc_count;
918 
919 #if PAN_ARCH <= 7
920    if (binding_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
921       ctx->desc_info.dyn_ubos.count += desc_count_diff;
922    } else if (binding_layout->type ==
923               VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
924       ctx->desc_info.dyn_ssbos.count += desc_count_diff;
925    } else {
926       uint32_t table =
927          desc_type_to_table_type(binding_layout->type, subdesc_idx);
928 
929       assert(table < PANVK_BIFROST_DESC_TABLE_COUNT);
930       ctx->desc_info.others[table].count += desc_count_diff;
931    }
932 #else
933    ctx->desc_info.dyn_bufs.count += desc_count_diff;
934 #endif
935 
936    he->data = (void *)(uintptr_t)new_desc_count;
937 }
938 
939 static uint32_t *
fill_copy_descs_for_binding(struct lower_desc_ctx * ctx,unsigned set,unsigned binding,uint32_t subdesc_idx,uint32_t desc_count)940 fill_copy_descs_for_binding(struct lower_desc_ctx *ctx, unsigned set,
941                             unsigned binding, uint32_t subdesc_idx,
942                             uint32_t desc_count)
943 {
944    assert(desc_count);
945 
946    const struct panvk_descriptor_set_layout *set_layout = ctx->set_layouts[set];
947    const struct panvk_descriptor_set_binding_layout *binding_layout =
948       &set_layout->bindings[binding];
949    uint32_t desc_stride = panvk_get_desc_stride(binding_layout->type);
950    uint32_t *first_entry = NULL;
951 
952    assert(desc_count <= binding_layout->desc_count);
953 
954    for (uint32_t i = 0; i < desc_count; i++) {
955       uint32_t src_idx =
956          binding_layout->desc_idx + (i * desc_stride) + subdesc_idx;
957       struct panvk_shader_desc_map *map;
958 
959 #if PAN_ARCH <= 7
960       if (binding_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
961          map = &ctx->desc_info.dyn_ubos;
962       } else if (binding_layout->type ==
963                  VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
964          map = &ctx->desc_info.dyn_ssbos;
965       } else {
966          uint32_t dst_table =
967             desc_type_to_table_type(binding_layout->type, subdesc_idx);
968 
969          assert(dst_table < PANVK_BIFROST_DESC_TABLE_COUNT);
970          map = &ctx->desc_info.others[dst_table];
971       }
972 #else
973       map = &ctx->desc_info.dyn_bufs;
974 #endif
975 
976       if (!first_entry)
977          first_entry = &map->map[map->count];
978 
979       map->map[map->count++] = COPY_DESC_HANDLE(set, src_idx);
980    }
981 
982    return first_entry;
983 }
984 
985 static void
create_copy_table(nir_shader * nir,struct lower_desc_ctx * ctx)986 create_copy_table(nir_shader *nir, struct lower_desc_ctx *ctx)
987 {
988    struct panvk_shader_desc_info *desc_info = &ctx->desc_info;
989    uint32_t copy_count;
990 
991 #if PAN_ARCH <= 7
992    copy_count = desc_info->dyn_ubos.count + desc_info->dyn_ssbos.count;
993    for (uint32_t i = 0; i < PANVK_BIFROST_DESC_TABLE_COUNT; i++)
994       copy_count += desc_info->others[i].count;
995 #else
996    copy_count = desc_info->dyn_bufs.count + desc_info->dyn_bufs.count;
997 #endif
998 
999    if (copy_count == 0)
1000       return;
1001 
1002 #if PAN_ARCH <= 7
1003    uint32_t *copy_table = rzalloc_array(ctx->ht, uint32_t, copy_count);
1004 
1005    assert(copy_table);
1006    desc_info->dyn_ubos.map = copy_table;
1007    copy_table += desc_info->dyn_ubos.count;
1008    desc_info->dyn_ubos.count = 0;
1009    desc_info->dyn_ssbos.map = copy_table;
1010    copy_table += desc_info->dyn_ssbos.count;
1011    desc_info->dyn_ssbos.count = 0;
1012 
1013    for (uint32_t i = 0; i < PANVK_BIFROST_DESC_TABLE_COUNT; i++) {
1014       desc_info->others[i].map = copy_table;
1015       copy_table += desc_info->others[i].count;
1016       desc_info->others[i].count = 0;
1017    }
1018 #else
1019    desc_info->dyn_bufs.map = rzalloc_array(ctx->ht, uint32_t, copy_count);
1020    assert(desc_info->dyn_bufs.map);
1021 #endif
1022 
1023    hash_table_foreach(ctx->ht, he) {
1024       /* We use the upper binding bit to encode the subdesc index. */
1025       uint32_t desc_count = (uintptr_t)he->data;
1026       struct desc_id src = key_to_desc_id(he->key);
1027 
1028       /* Until now, we were just using the hash table to track descriptors
1029        * count, but after that point, it's a <set,binding> -> <table_index>
1030        * map. */
1031       he->data = fill_copy_descs_for_binding(ctx, src.set, src.binding,
1032                                              src.subdesc, desc_count);
1033    }
1034 
1035 #if PAN_ARCH >= 9
1036    /* Dummy sampler comes after the vertex attributes. */
1037    uint32_t dummy_sampler_idx = nir->info.stage == MESA_SHADER_VERTEX ? 16 : 0;
1038    desc_info->dummy_sampler_handle = pan_res_handle(0, dummy_sampler_idx);
1039 
1040    /* Dynamic buffers come after the dummy sampler. */
1041    desc_info->dyn_bufs_start = dummy_sampler_idx + 1;
1042 #endif
1043 }
1044 
1045 /* TODO: Texture instructions support bindless through DTSEL_IMM(63),
1046  * which would save us copies of the texture/sampler descriptors. */
1047 static bool
collect_tex_desc_access(nir_builder * b,nir_tex_instr * tex,struct lower_desc_ctx * ctx)1048 collect_tex_desc_access(nir_builder *b, nir_tex_instr *tex,
1049                         struct lower_desc_ctx *ctx)
1050 {
1051    bool recorded = false;
1052    int sampler_src_idx =
1053       nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
1054    if (sampler_src_idx >= 0) {
1055       nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src);
1056 
1057       uint32_t set, binding, index_imm, max_idx;
1058       nir_def *index_ssa;
1059       get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
1060                                  &max_idx);
1061 
1062       record_binding(ctx, set, binding, VK_DESCRIPTOR_TYPE_SAMPLER, max_idx);
1063       recorded = true;
1064    }
1065 
1066    int tex_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
1067    if (tex_src_idx >= 0) {
1068       nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_src_idx].src);
1069 
1070       uint32_t set, binding, index_imm, max_idx;
1071       nir_def *index_ssa;
1072       get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
1073                                  &max_idx);
1074 
1075       record_binding(ctx, set, binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1076                      max_idx);
1077       recorded = true;
1078    }
1079 
1080    return recorded;
1081 }
1082 
1083 static bool
collect_intr_desc_access(nir_builder * b,nir_intrinsic_instr * intrin,struct lower_desc_ctx * ctx)1084 collect_intr_desc_access(nir_builder *b, nir_intrinsic_instr *intrin,
1085                          struct lower_desc_ctx *ctx)
1086 {
1087    switch (intrin->intrinsic) {
1088    case nir_intrinsic_vulkan_resource_index: {
1089       unsigned set, binding;
1090 
1091       set = nir_intrinsic_desc_set(intrin);
1092       binding = nir_intrinsic_binding(intrin);
1093 
1094       /* TODO: walk the reindex chain from load_vulkan_descriptor() to try and
1095        * guess the max index. */
1096       record_binding(ctx, set, binding, ~0, UINT32_MAX);
1097       return true;
1098    }
1099 
1100    case nir_intrinsic_image_deref_store:
1101    case nir_intrinsic_image_deref_load:
1102    case nir_intrinsic_image_deref_atomic:
1103    case nir_intrinsic_image_deref_atomic_swap:
1104    case nir_intrinsic_image_deref_size:
1105    case nir_intrinsic_image_deref_samples: {
1106       nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
1107       unsigned set, binding, index_imm, max_idx;
1108       nir_def *index_ssa;
1109 
1110       get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa,
1111                                  &max_idx);
1112       record_binding(ctx, set, binding, ~0, max_idx);
1113       return true;
1114    }
1115    default:
1116       return false;
1117    }
1118 }
1119 
1120 static bool
collect_instr_desc_access(nir_builder * b,nir_instr * instr,void * data)1121 collect_instr_desc_access(nir_builder *b, nir_instr *instr, void *data)
1122 {
1123    struct lower_desc_ctx *ctx = data;
1124 
1125    switch (instr->type) {
1126    case nir_instr_type_tex:
1127       return collect_tex_desc_access(b, nir_instr_as_tex(instr), ctx);
1128    case nir_instr_type_intrinsic:
1129       return collect_intr_desc_access(b, nir_instr_as_intrinsic(instr), ctx);
1130    default:
1131       return false;
1132    }
1133 }
1134 
1135 static void
upload_shader_desc_info(struct panvk_device * dev,struct panvk_shader * shader,const struct panvk_shader_desc_info * desc_info)1136 upload_shader_desc_info(struct panvk_device *dev, struct panvk_shader *shader,
1137                         const struct panvk_shader_desc_info *desc_info)
1138 {
1139 #if PAN_ARCH <= 7
1140    unsigned copy_count = 0;
1141    for (unsigned i = 0; i < ARRAY_SIZE(shader->desc_info.others.count); i++) {
1142       shader->desc_info.others.count[i] = desc_info->others[i].count;
1143       copy_count += desc_info->others[i].count;
1144    }
1145 
1146    if (copy_count > 0) {
1147       shader->desc_info.others.map = panvk_pool_upload_aligned(
1148          &dev->mempools.rw, desc_info->others[0].map,
1149          copy_count * sizeof(uint32_t), sizeof(uint32_t));
1150    }
1151 
1152    assert(desc_info->dyn_ubos.count <
1153           ARRAY_SIZE(shader->desc_info.dyn_ubos.map));
1154    shader->desc_info.dyn_ubos.count = desc_info->dyn_ubos.count;
1155    memcpy(shader->desc_info.dyn_ubos.map, desc_info->dyn_ubos.map,
1156           desc_info->dyn_ubos.count * sizeof(*shader->desc_info.dyn_ubos.map));
1157    assert(desc_info->dyn_ssbos.count <
1158           ARRAY_SIZE(shader->desc_info.dyn_ssbos.map));
1159    shader->desc_info.dyn_ssbos.count = desc_info->dyn_ssbos.count;
1160    memcpy(
1161       shader->desc_info.dyn_ssbos.map, desc_info->dyn_ssbos.map,
1162       desc_info->dyn_ssbos.count * sizeof(*shader->desc_info.dyn_ssbos.map));
1163 #else
1164    assert(desc_info->dyn_bufs.count <
1165           ARRAY_SIZE(shader->desc_info.dyn_bufs.map));
1166    shader->desc_info.dyn_bufs.count = desc_info->dyn_bufs.count;
1167    memcpy(shader->desc_info.dyn_bufs.map, desc_info->dyn_bufs.map,
1168           desc_info->dyn_bufs.count * sizeof(*shader->desc_info.dyn_bufs.map));
1169 #endif
1170 
1171    shader->desc_info.used_set_mask = desc_info->used_set_mask;
1172 }
1173 
1174 bool
panvk_per_arch(nir_lower_descriptors)1175 panvk_per_arch(nir_lower_descriptors)(
1176    nir_shader *nir, struct panvk_device *dev, uint32_t set_layout_count,
1177    struct vk_descriptor_set_layout *const *set_layouts,
1178    struct panvk_shader *shader)
1179 {
1180    struct lower_desc_ctx ctx = {0};
1181    bool progress;
1182 
1183 #if PAN_ARCH <= 7
1184    ctx.ubo_addr_format = nir_address_format_32bit_index_offset;
1185    ctx.ssbo_addr_format = dev->vk.enabled_features.robustBufferAccess
1186                              ? nir_address_format_64bit_bounded_global
1187                              : nir_address_format_64bit_global_32bit_offset;
1188 #else
1189    ctx.ubo_addr_format = nir_address_format_vec2_index_32bit_offset;
1190    ctx.ssbo_addr_format = nir_address_format_vec2_index_32bit_offset;
1191 #endif
1192 
1193    ctx.ht = _mesa_hash_table_create_u32_keys(NULL);
1194    assert(ctx.ht);
1195 
1196    _mesa_hash_table_set_deleted_key(ctx.ht, DELETED_KEY);
1197 
1198    for (uint32_t i = 0; i < set_layout_count; i++)
1199       ctx.set_layouts[i] = to_panvk_descriptor_set_layout(set_layouts[i]);
1200 
1201    progress = nir_shader_instructions_pass(nir, collect_instr_desc_access,
1202                                            nir_metadata_all, &ctx);
1203    if (!progress)
1204       goto out;
1205 
1206    create_copy_table(nir, &ctx);
1207    upload_shader_desc_info(dev, shader, &ctx.desc_info);
1208 
1209    progress = nir_shader_instructions_pass(nir, lower_descriptors_instr,
1210                                            nir_metadata_control_flow, &ctx);
1211 
1212 out:
1213    _mesa_hash_table_destroy(ctx.ht, NULL);
1214    return progress;
1215 }
1216