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