xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/zink/zink_descriptors.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2020 Mike Blumenkrantz
3  * Copyright © 2022 Valve Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Mike Blumenkrantz <[email protected]>
26  */
27 
28 #include "zink_context.h"
29 #include "zink_compiler.h"
30 #include "zink_descriptors.h"
31 #include "zink_program.h"
32 #include "zink_render_pass.h"
33 #include "zink_resource.h"
34 #include "zink_screen.h"
35 
36 #define XXH_INLINE_ALL
37 #include "util/xxhash.h"
38 
39 static VkDescriptorSetLayout
descriptor_layout_create(struct zink_screen * screen,enum zink_descriptor_type t,VkDescriptorSetLayoutBinding * bindings,unsigned num_bindings)40 descriptor_layout_create(struct zink_screen *screen, enum zink_descriptor_type t, VkDescriptorSetLayoutBinding *bindings, unsigned num_bindings)
41 {
42    VkDescriptorSetLayout dsl;
43    VkDescriptorSetLayoutCreateInfo dcslci = {0};
44    dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
45    dcslci.pNext = NULL;
46    VkDescriptorSetLayoutBindingFlagsCreateInfo fci = {0};
47    VkDescriptorBindingFlags flags[ZINK_MAX_DESCRIPTORS_PER_TYPE];
48    dcslci.pNext = &fci;
49    /* TODO bindless */
50    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && t != ZINK_DESCRIPTOR_BINDLESS)
51       dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
52    else if (t == ZINK_DESCRIPTOR_TYPE_UNIFORMS)
53       dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
54    fci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
55    fci.bindingCount = num_bindings;
56    fci.pBindingFlags = flags;
57    for (unsigned i = 0; i < num_bindings; i++) {
58       flags[i] = 0;
59    }
60    dcslci.bindingCount = num_bindings;
61    dcslci.pBindings = bindings;
62    VkDescriptorSetLayoutSupport supp;
63    supp.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT;
64    supp.pNext = NULL;
65    supp.supported = VK_FALSE;
66    if (VKSCR(GetDescriptorSetLayoutSupport)) {
67       VKSCR(GetDescriptorSetLayoutSupport)(screen->dev, &dcslci, &supp);
68       if (supp.supported == VK_FALSE) {
69          debug_printf("vkGetDescriptorSetLayoutSupport claims layout is unsupported\n");
70          return VK_NULL_HANDLE;
71       }
72    }
73    VkResult result = VKSCR(CreateDescriptorSetLayout)(screen->dev, &dcslci, 0, &dsl);
74    if (result != VK_SUCCESS)
75       mesa_loge("ZINK: vkCreateDescriptorSetLayout failed (%s)", vk_Result_to_str(result));
76    return dsl;
77 }
78 
79 static uint32_t
hash_descriptor_layout(const void * key)80 hash_descriptor_layout(const void *key)
81 {
82    uint32_t hash = 0;
83    const struct zink_descriptor_layout_key *k = key;
84    hash = XXH32(&k->num_bindings, sizeof(unsigned), hash);
85    /* only hash first 3 members: no holes and the rest are always constant */
86    for (unsigned i = 0; i < k->num_bindings; i++)
87       hash = XXH32(&k->bindings[i], offsetof(VkDescriptorSetLayoutBinding, stageFlags), hash);
88 
89    return hash;
90 }
91 
92 static bool
equals_descriptor_layout(const void * a,const void * b)93 equals_descriptor_layout(const void *a, const void *b)
94 {
95    const struct zink_descriptor_layout_key *a_k = a;
96    const struct zink_descriptor_layout_key *b_k = b;
97    return a_k->num_bindings == b_k->num_bindings &&
98           (!a_k->num_bindings || !memcmp(a_k->bindings, b_k->bindings, a_k->num_bindings * sizeof(VkDescriptorSetLayoutBinding)));
99 }
100 
101 static struct zink_descriptor_layout *
create_layout(struct zink_screen * screen,enum zink_descriptor_type type,VkDescriptorSetLayoutBinding * bindings,unsigned num_bindings,struct zink_descriptor_layout_key ** layout_key)102 create_layout(struct zink_screen *screen, enum zink_descriptor_type type,
103               VkDescriptorSetLayoutBinding *bindings, unsigned num_bindings,
104               struct zink_descriptor_layout_key **layout_key)
105 {
106    VkDescriptorSetLayout dsl = descriptor_layout_create(screen, type, bindings, num_bindings);
107    if (!dsl)
108       return NULL;
109 
110    size_t bindings_size = num_bindings * sizeof(VkDescriptorSetLayoutBinding);
111    struct zink_descriptor_layout_key *k = ralloc_size(screen, sizeof(struct zink_descriptor_layout_key) + bindings_size);
112    k->num_bindings = num_bindings;
113    if (num_bindings) {
114       k->bindings = (void *)(k + 1);
115       memcpy(k->bindings, bindings, bindings_size);
116    }
117 
118    struct zink_descriptor_layout *layout = rzalloc(screen, struct zink_descriptor_layout);
119    layout->layout = dsl;
120    *layout_key = k;
121    return layout;
122 }
123 
124 static struct zink_descriptor_layout *
descriptor_util_layout_get(struct zink_screen * screen,enum zink_descriptor_type type,VkDescriptorSetLayoutBinding * bindings,unsigned num_bindings,struct zink_descriptor_layout_key ** layout_key)125 descriptor_util_layout_get(struct zink_screen *screen, enum zink_descriptor_type type,
126                       VkDescriptorSetLayoutBinding *bindings, unsigned num_bindings,
127                       struct zink_descriptor_layout_key **layout_key)
128 {
129    uint32_t hash = 0;
130    struct zink_descriptor_layout_key key = {
131       .num_bindings = num_bindings,
132       .bindings = bindings,
133    };
134 
135    /* push descriptor layouts are unique and can't be reused */
136    if (type != ZINK_DESCRIPTOR_TYPE_UNIFORMS) {
137       hash = hash_descriptor_layout(&key);
138       simple_mtx_lock(&screen->desc_set_layouts_lock);
139       struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&screen->desc_set_layouts[type], hash, &key);
140       simple_mtx_unlock(&screen->desc_set_layouts_lock);
141       if (he) {
142          *layout_key = (void*)he->key;
143          return he->data;
144       }
145    }
146 
147    struct zink_descriptor_layout *layout = create_layout(screen, type, bindings, num_bindings, layout_key);
148    if (layout && type != ZINK_DESCRIPTOR_TYPE_UNIFORMS) {
149       simple_mtx_lock(&screen->desc_set_layouts_lock);
150       _mesa_hash_table_insert_pre_hashed(&screen->desc_set_layouts[type], hash, *layout_key, layout);
151       simple_mtx_unlock(&screen->desc_set_layouts_lock);
152    }
153    return layout;
154 }
155 
156 
157 static uint32_t
hash_descriptor_pool_key(const void * key)158 hash_descriptor_pool_key(const void *key)
159 {
160    uint32_t hash = 0;
161    const struct zink_descriptor_pool_key *k = key;
162    hash = XXH32(&k->layout, sizeof(void*), hash);
163    for (unsigned i = 0; i < k->num_type_sizes; i++)
164       hash = XXH32(&k->sizes[i], sizeof(VkDescriptorPoolSize), hash);
165 
166    return hash;
167 }
168 
169 static bool
equals_descriptor_pool_key(const void * a,const void * b)170 equals_descriptor_pool_key(const void *a, const void *b)
171 {
172    const struct zink_descriptor_pool_key *a_k = a;
173    const struct zink_descriptor_pool_key *b_k = b;
174    const unsigned a_num_type_sizes = a_k->num_type_sizes;
175    const unsigned b_num_type_sizes = b_k->num_type_sizes;
176    return a_k->layout == b_k->layout &&
177           a_num_type_sizes == b_num_type_sizes &&
178           !memcmp(a_k->sizes, b_k->sizes, b_num_type_sizes * sizeof(VkDescriptorPoolSize));
179 }
180 
181 static struct zink_descriptor_pool_key *
descriptor_util_pool_key_get(struct zink_screen * screen,enum zink_descriptor_type type,struct zink_descriptor_layout_key * layout_key,VkDescriptorPoolSize * sizes,unsigned num_type_sizes)182 descriptor_util_pool_key_get(struct zink_screen *screen, enum zink_descriptor_type type,
183                                   struct zink_descriptor_layout_key *layout_key,
184                                   VkDescriptorPoolSize *sizes, unsigned num_type_sizes)
185 {
186    uint32_t hash = 0;
187    struct zink_descriptor_pool_key key;
188    key.num_type_sizes = num_type_sizes;
189    /* push descriptor pools can't be shared/reused by other types */
190    if (type != ZINK_DESCRIPTOR_TYPE_UNIFORMS) {
191       key.layout = layout_key;
192       memcpy(key.sizes, sizes, num_type_sizes * sizeof(VkDescriptorPoolSize));
193       hash = hash_descriptor_pool_key(&key);
194       simple_mtx_lock(&screen->desc_pool_keys_lock);
195       struct set_entry *he = _mesa_set_search_pre_hashed(&screen->desc_pool_keys[type], hash, &key);
196       simple_mtx_unlock(&screen->desc_pool_keys_lock);
197       if (he)
198          return (void*)he->key;
199    }
200 
201    struct zink_descriptor_pool_key *pool_key = rzalloc(screen, struct zink_descriptor_pool_key);
202    pool_key->layout = layout_key;
203    pool_key->num_type_sizes = num_type_sizes;
204    assert(pool_key->num_type_sizes);
205    memcpy(pool_key->sizes, sizes, num_type_sizes * sizeof(VkDescriptorPoolSize));
206    if (type != ZINK_DESCRIPTOR_TYPE_UNIFORMS) {
207       simple_mtx_lock(&screen->desc_pool_keys_lock);
208       _mesa_set_add_pre_hashed(&screen->desc_pool_keys[type], hash, pool_key);
209       pool_key->id = screen->desc_pool_keys[type].entries - 1;
210       simple_mtx_unlock(&screen->desc_pool_keys_lock);
211    }
212    return pool_key;
213 }
214 
215 static void
init_push_binding(VkDescriptorSetLayoutBinding * binding,unsigned i,VkDescriptorType type)216 init_push_binding(VkDescriptorSetLayoutBinding *binding, unsigned i, VkDescriptorType type)
217 {
218    binding->binding = i;
219    binding->descriptorType = type;
220    binding->descriptorCount = 1;
221    binding->stageFlags = mesa_to_vk_shader_stage(i);
222    binding->pImmutableSamplers = NULL;
223 }
224 
225 static VkDescriptorType
get_push_types(struct zink_screen * screen,enum zink_descriptor_type * dsl_type)226 get_push_types(struct zink_screen *screen, enum zink_descriptor_type *dsl_type)
227 {
228    *dsl_type = screen->info.have_KHR_push_descriptor ? ZINK_DESCRIPTOR_TYPE_UNIFORMS : ZINK_DESCRIPTOR_TYPE_UBO;
229    return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
230 }
231 
232 static struct zink_descriptor_layout *
create_gfx_layout(struct zink_context * ctx,struct zink_descriptor_layout_key ** layout_key,bool fbfetch)233 create_gfx_layout(struct zink_context *ctx, struct zink_descriptor_layout_key **layout_key, bool fbfetch)
234 {
235    struct zink_screen *screen = zink_screen(ctx->base.screen);
236    VkDescriptorSetLayoutBinding bindings[MESA_SHADER_STAGES];
237    enum zink_descriptor_type dsl_type;
238    VkDescriptorType vktype = get_push_types(screen, &dsl_type);
239    for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++)
240       init_push_binding(&bindings[i], i, vktype);
241    if (fbfetch) {
242       bindings[ZINK_GFX_SHADER_COUNT].binding = ZINK_FBFETCH_BINDING;
243       bindings[ZINK_GFX_SHADER_COUNT].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
244       bindings[ZINK_GFX_SHADER_COUNT].descriptorCount = 1;
245       bindings[ZINK_GFX_SHADER_COUNT].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
246       bindings[ZINK_GFX_SHADER_COUNT].pImmutableSamplers = NULL;
247    }
248    return create_layout(screen, dsl_type, bindings, fbfetch ? ARRAY_SIZE(bindings) : ARRAY_SIZE(bindings) - 1, layout_key);
249 }
250 
251 bool
zink_descriptor_util_push_layouts_get(struct zink_context * ctx,struct zink_descriptor_layout ** dsls,struct zink_descriptor_layout_key ** layout_keys)252 zink_descriptor_util_push_layouts_get(struct zink_context *ctx, struct zink_descriptor_layout **dsls, struct zink_descriptor_layout_key **layout_keys)
253 {
254    struct zink_screen *screen = zink_screen(ctx->base.screen);
255    VkDescriptorSetLayoutBinding compute_binding;
256    enum zink_descriptor_type dsl_type;
257    VkDescriptorType vktype = get_push_types(screen, &dsl_type);
258    init_push_binding(&compute_binding, MESA_SHADER_COMPUTE, vktype);
259    dsls[0] = create_gfx_layout(ctx, &layout_keys[0], false);
260    dsls[1] = create_layout(screen, dsl_type, &compute_binding, 1, &layout_keys[1]);
261    return dsls[0] && dsls[1];
262 }
263 
264 VkImageLayout
zink_descriptor_util_image_layout_eval(const struct zink_context * ctx,const struct zink_resource * res,bool is_compute)265 zink_descriptor_util_image_layout_eval(const struct zink_context *ctx, const struct zink_resource *res, bool is_compute)
266 {
267    if (res->bindless[0] || res->bindless[1]) {
268       /* bindless needs most permissive layout */
269       if (res->image_bind_count[0] || res->image_bind_count[1])
270          return VK_IMAGE_LAYOUT_GENERAL;
271       return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
272    }
273    if (res->image_bind_count[is_compute])
274       return VK_IMAGE_LAYOUT_GENERAL;
275    if (!is_compute && res->fb_bind_count && res->sampler_bind_count[0]) {
276       /* feedback loop */
277       if (!(res->obj->vkusage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) || zink_is_zsbuf_write(ctx)) {
278          if (zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout)
279             return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
280          return VK_IMAGE_LAYOUT_GENERAL;
281       }
282    }
283    if (res->obj->vkusage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
284       return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
285    return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
286 }
287 
288 bool
zink_descriptor_util_alloc_sets(struct zink_screen * screen,VkDescriptorSetLayout dsl,VkDescriptorPool pool,VkDescriptorSet * sets,unsigned num_sets)289 zink_descriptor_util_alloc_sets(struct zink_screen *screen, VkDescriptorSetLayout dsl, VkDescriptorPool pool, VkDescriptorSet *sets, unsigned num_sets)
290 {
291    VkDescriptorSetAllocateInfo dsai;
292    VkDescriptorSetLayout layouts[100];
293    assert(num_sets <= ARRAY_SIZE(layouts));
294    memset((void *)&dsai, 0, sizeof(dsai));
295    dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
296    dsai.pNext = NULL;
297    dsai.descriptorPool = pool;
298    dsai.descriptorSetCount = num_sets;
299    for (unsigned i = 0; i < num_sets; i ++)
300       layouts[i] = dsl;
301    dsai.pSetLayouts = layouts;
302 
303    VkResult result = VKSCR(AllocateDescriptorSets)(screen->dev, &dsai, sets);
304    if (result != VK_SUCCESS) {
305       mesa_loge("ZINK: %" PRIu64 " failed to allocate descriptor set :/ (%s)", (uint64_t)dsl, vk_Result_to_str(result));
306       return false;
307    }
308    return true;
309 }
310 
311 static void
init_db_template_entry(struct zink_screen * screen,struct zink_shader * shader,enum zink_descriptor_type type,unsigned idx,struct zink_descriptor_template * entry,unsigned * entry_idx)312 init_db_template_entry(struct zink_screen *screen, struct zink_shader *shader, enum zink_descriptor_type type,
313                        unsigned idx, struct zink_descriptor_template *entry, unsigned *entry_idx)
314 {
315     int index = shader->bindings[type][idx].index;
316     gl_shader_stage stage = clamp_stage(&shader->info);
317     entry->count = shader->bindings[type][idx].size;
318 
319     switch (shader->bindings[type][idx].type) {
320     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
321        entry->offset = offsetof(struct zink_context, di.db.ubos[stage][index]);
322        entry->stride = sizeof(VkDescriptorAddressInfoEXT);
323        entry->db_size = screen->info.db_props.robustUniformBufferDescriptorSize;
324        break;
325     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
326        entry->offset = offsetof(struct zink_context, di.textures[stage][index]);
327        entry->stride = sizeof(VkDescriptorImageInfo);
328        entry->db_size = screen->info.db_props.combinedImageSamplerDescriptorSize;
329        break;
330     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
331        entry->offset = offsetof(struct zink_context, di.textures[stage][index]);
332        entry->stride = sizeof(VkDescriptorImageInfo);
333        entry->db_size = screen->info.db_props.sampledImageDescriptorSize;
334        break;
335     case VK_DESCRIPTOR_TYPE_SAMPLER:
336        entry->offset = offsetof(struct zink_context, di.textures[stage][index]);
337        entry->stride = sizeof(VkDescriptorImageInfo);
338        entry->db_size = screen->info.db_props.samplerDescriptorSize;
339        break;
340     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
341        entry->offset = offsetof(struct zink_context, di.db.tbos[stage][index]);
342        entry->stride = sizeof(VkDescriptorAddressInfoEXT);
343        entry->db_size = screen->info.db_props.robustUniformTexelBufferDescriptorSize;
344        break;
345     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
346        entry->offset = offsetof(struct zink_context, di.db.ssbos[stage][index]);
347        entry->stride = sizeof(VkDescriptorAddressInfoEXT);
348        entry->db_size = screen->info.db_props.robustStorageBufferDescriptorSize;
349        break;
350     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
351        entry->offset = offsetof(struct zink_context, di.images[stage][index]);
352        entry->stride = sizeof(VkDescriptorImageInfo);
353        entry->db_size = screen->info.db_props.storageImageDescriptorSize;
354        break;
355     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
356        entry->offset = offsetof(struct zink_context, di.db.texel_images[stage][index]);
357        entry->stride = sizeof(VkDescriptorAddressInfoEXT);
358        entry->db_size = screen->info.db_props.robustStorageTexelBufferDescriptorSize;
359        break;
360     default:
361        unreachable("unknown type");
362     }
363     (*entry_idx)++;
364 }
365 
366 static void
init_template_entry(struct zink_shader * shader,enum zink_descriptor_type type,unsigned idx,VkDescriptorUpdateTemplateEntry * entry,unsigned * entry_idx)367 init_template_entry(struct zink_shader *shader, enum zink_descriptor_type type,
368                     unsigned idx, VkDescriptorUpdateTemplateEntry *entry, unsigned *entry_idx)
369 {
370     int index = shader->bindings[type][idx].index;
371     gl_shader_stage stage = clamp_stage(&shader->info);
372     entry->dstArrayElement = 0;
373     entry->dstBinding = shader->bindings[type][idx].binding;
374     entry->descriptorCount = shader->bindings[type][idx].size;
375     if (shader->bindings[type][idx].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
376        /* filter out DYNAMIC type here since this is just the uniform set */
377        entry->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
378     else
379        entry->descriptorType = shader->bindings[type][idx].type;
380     switch (shader->bindings[type][idx].type) {
381     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
382     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
383        entry->offset = offsetof(struct zink_context, di.t.ubos[stage][index]);
384        entry->stride = sizeof(VkDescriptorBufferInfo);
385        break;
386     case VK_DESCRIPTOR_TYPE_SAMPLER:
387     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
388     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
389        entry->offset = offsetof(struct zink_context, di.textures[stage][index]);
390        entry->stride = sizeof(VkDescriptorImageInfo);
391        break;
392     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
393        entry->offset = offsetof(struct zink_context, di.t.tbos[stage][index]);
394        entry->stride = sizeof(VkBufferView);
395        break;
396     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
397        entry->offset = offsetof(struct zink_context, di.t.ssbos[stage][index]);
398        entry->stride = sizeof(VkDescriptorBufferInfo);
399        break;
400     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
401        entry->offset = offsetof(struct zink_context, di.images[stage][index]);
402        entry->stride = sizeof(VkDescriptorImageInfo);
403        break;
404     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
405        entry->offset = offsetof(struct zink_context, di.t.texel_images[stage][index]);
406        entry->stride = sizeof(VkBufferView);
407        break;
408     default:
409        unreachable("unknown type");
410     }
411     (*entry_idx)++;
412 }
413 
414 static void
init_program_db(struct zink_screen * screen,struct zink_program * pg,enum zink_descriptor_type type,VkDescriptorSetLayoutBinding * bindings,unsigned num_bindings,VkDescriptorSetLayout dsl)415 init_program_db(struct zink_screen *screen, struct zink_program *pg, enum zink_descriptor_type type, VkDescriptorSetLayoutBinding *bindings, unsigned num_bindings, VkDescriptorSetLayout dsl)
416 {
417    VkDeviceSize val;
418    VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, dsl, &val);
419    pg->dd.db_size[type] = align64(val, screen->info.db_props.descriptorBufferOffsetAlignment);
420    pg->dd.db_offset[type] = rzalloc_array(pg, uint32_t, num_bindings);
421    for (unsigned i = 0; i < num_bindings; i++) {
422       VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, dsl, bindings[i].binding, &val);
423       pg->dd.db_offset[type][i] = val;
424    }
425 }
426 
427 static uint16_t
descriptor_program_num_sizes(VkDescriptorPoolSize * sizes,enum zink_descriptor_type type)428 descriptor_program_num_sizes(VkDescriptorPoolSize *sizes, enum zink_descriptor_type type)
429 {
430    switch (type) {
431    case ZINK_DESCRIPTOR_TYPE_UBO:
432       return !!sizes[ZDS_INDEX_UBO].descriptorCount;
433    case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
434       return !!sizes[ZDS_INDEX_COMBINED_SAMPLER].descriptorCount +
435              !!sizes[ZDS_INDEX_UNIFORM_TEXELS].descriptorCount +
436              !!sizes[ZDS_INDEX_SAMPLER].descriptorCount;
437    case ZINK_DESCRIPTOR_TYPE_SSBO:
438       return !!sizes[ZDS_INDEX_STORAGE_BUFFER].descriptorCount;
439    case ZINK_DESCRIPTOR_TYPE_IMAGE:
440       return !!sizes[ZDS_INDEX_STORAGE_IMAGE].descriptorCount +
441              !!sizes[ZDS_INDEX_STORAGE_TEXELS].descriptorCount;
442    default: break;
443    }
444    unreachable("unknown type");
445 }
446 
447 static uint16_t
descriptor_program_num_sizes_compact(VkDescriptorPoolSize * sizes,unsigned desc_set)448 descriptor_program_num_sizes_compact(VkDescriptorPoolSize *sizes, unsigned desc_set)
449 {
450    switch (desc_set) {
451    case ZINK_DESCRIPTOR_TYPE_UBO:
452       return !!sizes[ZDS_INDEX_COMP_UBO].descriptorCount + !!sizes[ZDS_INDEX_COMP_STORAGE_BUFFER].descriptorCount;
453    case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
454       return !!sizes[ZDS_INDEX_COMP_COMBINED_SAMPLER].descriptorCount +
455              !!sizes[ZDS_INDEX_COMP_UNIFORM_TEXELS].descriptorCount +
456              !!sizes[ZDS_INDEX_COMP_SAMPLER].descriptorCount +
457              !!sizes[ZDS_INDEX_COMP_STORAGE_IMAGE].descriptorCount +
458              !!sizes[ZDS_INDEX_COMP_STORAGE_TEXELS].descriptorCount;
459    case ZINK_DESCRIPTOR_TYPE_SSBO:
460    case ZINK_DESCRIPTOR_TYPE_IMAGE:
461    default: break;
462    }
463    unreachable("unknown type");
464 }
465 
466 /* create all the descriptor objects for a program:
467  * called during program creation
468  * may be called from threads (no unsafe ctx use!)
469  */
470 bool
zink_descriptor_program_init(struct zink_context * ctx,struct zink_program * pg)471 zink_descriptor_program_init(struct zink_context *ctx, struct zink_program *pg)
472 {
473    struct zink_screen *screen = zink_screen(ctx->base.screen);
474    VkDescriptorSetLayoutBinding bindings[ZINK_DESCRIPTOR_BASE_TYPES][MESA_SHADER_STAGES * 64];
475    VkDescriptorUpdateTemplateEntry entries[ZINK_DESCRIPTOR_BASE_TYPES][MESA_SHADER_STAGES * 64];
476    unsigned num_bindings[ZINK_DESCRIPTOR_BASE_TYPES] = {0};
477    uint8_t has_bindings = 0;
478    unsigned push_count = 0;
479    uint16_t num_type_sizes[ZINK_DESCRIPTOR_BASE_TYPES];
480    VkDescriptorPoolSize sizes[ZDS_INDEX_MAX] = {0}; //zink_descriptor_size_index
481 
482    struct zink_shader **stages;
483    if (pg->is_compute)
484       stages = &((struct zink_compute_program*)pg)->shader;
485    else
486       stages = ((struct zink_gfx_program*)pg)->shaders;
487 
488    if (!pg->is_compute && stages[MESA_SHADER_FRAGMENT]->info.fs.uses_fbfetch_output) {
489       push_count = 1;
490       pg->dd.fbfetch = true;
491    }
492 
493    unsigned entry_idx[ZINK_DESCRIPTOR_BASE_TYPES] = {0};
494    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
495       unsigned desc_set_size[ZINK_DESCRIPTOR_BASE_TYPES];
496       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
497          desc_set_size[i] = zink_program_num_bindings_typed(pg, i);
498       if (screen->compact_descriptors) {
499          desc_set_size[ZINK_DESCRIPTOR_TYPE_UBO] += desc_set_size[ZINK_DESCRIPTOR_TYPE_SSBO];
500          desc_set_size[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] += desc_set_size[ZINK_DESCRIPTOR_TYPE_IMAGE];
501          desc_set_size[ZINK_DESCRIPTOR_TYPE_SSBO] = 0;
502          desc_set_size[ZINK_DESCRIPTOR_TYPE_IMAGE] = 0;
503       }
504       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
505          if (desc_set_size[i])
506             pg->dd.db_template[i] = rzalloc_array(pg, struct zink_descriptor_template, desc_set_size[i]);
507       }
508    }
509 
510    unsigned num_shaders = pg->is_compute ? 1 : ZINK_GFX_SHADER_COUNT;
511    bool have_push = screen->info.have_KHR_push_descriptor;
512    /* iterate over the shaders and generate binding/layout/template structs */
513    for (int i = 0; i < num_shaders; i++) {
514       struct zink_shader *shader = stages[i];
515       if (!shader)
516          continue;
517 
518       gl_shader_stage stage = clamp_stage(&shader->info);
519       VkShaderStageFlagBits stage_flags = mesa_to_vk_shader_stage(stage);
520       /* uniform ubos handled in push */
521       if (shader->has_uniforms) {
522          pg->dd.push_usage |= BITFIELD64_BIT(stage);
523          push_count++;
524       }
525       for (int j = 0; j < ZINK_DESCRIPTOR_BASE_TYPES; j++) {
526          unsigned desc_type = screen->desc_set_id[j] - 1;
527          for (int k = 0; k < shader->num_bindings[j]; k++) {
528             assert(num_bindings[desc_type] < ARRAY_SIZE(bindings[desc_type]));
529             VkDescriptorSetLayoutBinding *binding = &bindings[desc_type][num_bindings[desc_type]];
530             binding->binding = shader->bindings[j][k].binding;
531             binding->descriptorType = shader->bindings[j][k].type;
532             binding->descriptorCount = shader->bindings[j][k].size;
533             binding->stageFlags = stage_flags;
534             binding->pImmutableSamplers = NULL;
535 
536             unsigned idx = screen->compact_descriptors ? zink_vktype_to_size_idx_comp(shader->bindings[j][k].type) :
537                                                          zink_vktype_to_size_idx(shader->bindings[j][k].type);
538             sizes[idx].descriptorCount += shader->bindings[j][k].size;
539             sizes[idx].type = shader->bindings[j][k].type;
540             if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
541                init_db_template_entry(screen, shader, j, k, &pg->dd.db_template[desc_type][entry_idx[desc_type]], &entry_idx[desc_type]);
542             else
543                init_template_entry(shader, j, k, &entries[desc_type][entry_idx[desc_type]], &entry_idx[desc_type]);
544             num_bindings[desc_type]++;
545             has_bindings |= BITFIELD_BIT(desc_type);
546          }
547          num_type_sizes[desc_type] = screen->compact_descriptors ?
548                                     descriptor_program_num_sizes_compact(sizes, desc_type) :
549                                     descriptor_program_num_sizes(sizes, j);
550       }
551       pg->dd.bindless |= shader->bindless;
552    }
553    pg->dd.binding_usage = has_bindings;
554    if (!has_bindings && !push_count && !pg->dd.bindless) {
555       pg->layout = zink_pipeline_layout_create(screen, pg->dsl, pg->num_dsl, pg->is_compute, 0);
556       if (pg->layout)
557          pg->compat_id = _mesa_hash_data(pg->dsl, pg->num_dsl * sizeof(pg->dsl[0]));
558       return !!pg->layout;
559    }
560 
561    pg->dsl[pg->num_dsl++] = push_count ? ctx->dd.push_dsl[pg->is_compute]->layout : ctx->dd.dummy_dsl->layout;
562    /* iterate over the found descriptor types and create layouts / pool keys */
563    if (has_bindings) {
564       for (unsigned i = 0; i < ARRAY_SIZE(sizes); i++)
565          sizes[i].descriptorCount *= MAX_LAZY_DESCRIPTORS;
566       u_foreach_bit(desc_type, has_bindings) {
567          /* descriptor sets must be bound contiguously, so add null sets for any that are "missing" */
568          for (unsigned i = 0; i < desc_type; i++) {
569             /* push set is always 0 */
570             if (!pg->dsl[i + 1]) {
571                /* inject a null dsl */
572                pg->dsl[pg->num_dsl++] = ctx->dd.dummy_dsl->layout;
573                pg->dd.binding_usage |= BITFIELD_BIT(i);
574             }
575          }
576          struct zink_descriptor_layout_key *key;
577          pg->dd.layouts[pg->num_dsl] = descriptor_util_layout_get(screen, desc_type, bindings[desc_type], num_bindings[desc_type], &key);
578          unsigned idx = screen->compact_descriptors ? zink_descriptor_type_to_size_idx_comp(desc_type) :
579                                                       zink_descriptor_type_to_size_idx(desc_type);
580          /* some sets can have multiple descriptor types: ensure the size arrays for these types are contiguous for creating the pool key */
581          VkDescriptorPoolSize *sz = &sizes[idx];
582          VkDescriptorPoolSize sz2[5];
583          if (screen->compact_descriptors || (pg->is_compute && stages[0]->info.stage == MESA_SHADER_KERNEL)) {
584             unsigned found = 0;
585             while (found < num_type_sizes[desc_type]) {
586                if (sz->descriptorCount) {
587                   memcpy(&sz2[found], sz, sizeof(VkDescriptorPoolSize));
588                   found++;
589                }
590                sz++;
591             }
592             sz = sz2;
593          } else {
594             if (!sz->descriptorCount)
595                sz++;
596          }
597          pg->dd.pool_key[desc_type] = descriptor_util_pool_key_get(screen, desc_type, key, sz, num_type_sizes[desc_type]);
598          pg->dd.pool_key[desc_type]->use_count++;
599          pg->dsl[pg->num_dsl] = pg->dd.layouts[pg->num_dsl]->layout;
600          if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
601             init_program_db(screen, pg, desc_type, bindings[desc_type], num_bindings[desc_type], pg->dsl[pg->num_dsl]);
602          pg->num_dsl++;
603       }
604    }
605    /* TODO: make this dynamic so that bindless set id can be 0 if no other descriptors are used? */
606    if (pg->dd.bindless) {
607       unsigned desc_set = screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS];
608       pg->num_dsl = desc_set + 1;
609       pg->dsl[desc_set] = screen->bindless_layout;
610       /* separate handling for null set injection when only bindless descriptors are used */
611       for (unsigned i = 0; i < desc_set; i++) {
612          if (!pg->dsl[i]) {
613             /* inject a null dsl */
614             pg->dsl[i] = ctx->dd.dummy_dsl->layout;
615             if (i != screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UNIFORMS])
616                pg->dd.binding_usage |= BITFIELD_BIT(i);
617          }
618       }
619       /* all lower id sets are guaranteed to be used */
620       pg->dd.binding_usage |= BITFIELD_MASK(ZINK_DESCRIPTOR_BASE_TYPES);
621    }
622 
623    pg->layout = zink_pipeline_layout_create(screen, pg->dsl, pg->num_dsl, pg->is_compute, 0);
624    if (!pg->layout)
625       return false;
626    pg->compat_id = _mesa_hash_data(pg->dsl, pg->num_dsl * sizeof(pg->dsl[0]));
627 
628    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
629       return true;
630 
631    VkDescriptorUpdateTemplateCreateInfo template[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES] = {0};
632    /* type of template */
633    VkDescriptorUpdateTemplateType types[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES] = {VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET};
634    if (have_push)
635       types[0] = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
636 
637    /* number of descriptors in template */
638    unsigned wd_count[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES];
639    if (push_count)
640       wd_count[0] = pg->is_compute ? 1 : (ZINK_GFX_SHADER_COUNT + !!ctx->dd.has_fbfetch);
641    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
642       wd_count[i + 1] = pg->dd.pool_key[i] ? pg->dd.pool_key[i]->layout->num_bindings : 0;
643 
644    VkDescriptorUpdateTemplateEntry *push_entries[2] = {
645       ctx->dd.push_entries,
646       &ctx->dd.compute_push_entry,
647    };
648    for (unsigned i = 0; i < pg->num_dsl; i++) {
649       bool is_push = i == 0;
650       /* no need for empty templates */
651       if (pg->dsl[i] == ctx->dd.dummy_dsl->layout ||
652           pg->dsl[i] == screen->bindless_layout ||
653           (!is_push && pg->dd.templates[i]))
654          continue;
655       template[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
656       assert(wd_count[i]);
657       template[i].descriptorUpdateEntryCount = wd_count[i];
658       if (is_push)
659          template[i].pDescriptorUpdateEntries = push_entries[pg->is_compute];
660       else
661          template[i].pDescriptorUpdateEntries = entries[i - 1];
662       template[i].templateType = types[i];
663       template[i].descriptorSetLayout = pg->dsl[i];
664       template[i].pipelineBindPoint = pg->is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
665       template[i].pipelineLayout = pg->layout;
666       template[i].set = i;
667       VkDescriptorUpdateTemplate t;
668       if (VKSCR(CreateDescriptorUpdateTemplate)(screen->dev, &template[i], NULL, &t) != VK_SUCCESS)
669          return false;
670       pg->dd.templates[i] = t;
671    }
672    return true;
673 }
674 
675 void
zink_descriptor_shader_get_binding_offsets(const struct zink_shader * shader,unsigned * offsets)676 zink_descriptor_shader_get_binding_offsets(const struct zink_shader *shader, unsigned *offsets)
677 {
678    offsets[ZINK_DESCRIPTOR_TYPE_UBO] = 0;
679    offsets[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = (shader->num_bindings[ZINK_DESCRIPTOR_TYPE_UBO] ?
680                                                 shader->bindings[ZINK_DESCRIPTOR_TYPE_UBO][shader->num_bindings[ZINK_DESCRIPTOR_TYPE_UBO] - 1].binding + 1 :
681                                                 1);
682    offsets[ZINK_DESCRIPTOR_TYPE_SSBO] = offsets[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] + (shader->num_bindings[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] ?
683                                                                                      shader->bindings[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][shader->num_bindings[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] - 1].binding + 1 :
684                                                                                      1);
685    offsets[ZINK_DESCRIPTOR_TYPE_IMAGE] = offsets[ZINK_DESCRIPTOR_TYPE_SSBO] + (shader->num_bindings[ZINK_DESCRIPTOR_TYPE_SSBO] ?
686                                                                               shader->bindings[ZINK_DESCRIPTOR_TYPE_SSBO][shader->num_bindings[ZINK_DESCRIPTOR_TYPE_SSBO] - 1].binding + 1 :
687                                                                               1);
688 }
689 
690 void
zink_descriptor_shader_init(struct zink_screen * screen,struct zink_shader * shader)691 zink_descriptor_shader_init(struct zink_screen *screen, struct zink_shader *shader)
692 {
693    VkDescriptorSetLayoutBinding bindings[ZINK_DESCRIPTOR_BASE_TYPES * ZINK_MAX_DESCRIPTORS_PER_TYPE];
694    unsigned num_bindings = 0;
695    VkShaderStageFlagBits stage_flags = mesa_to_vk_shader_stage(clamp_stage(&shader->info));
696 
697    unsigned desc_set_size = shader->has_uniforms;
698    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
699       desc_set_size += shader->num_bindings[i];
700    if (desc_set_size)
701       shader->precompile.db_template = rzalloc_array(shader, struct zink_descriptor_template, desc_set_size);
702 
703    if (shader->has_uniforms) {
704       VkDescriptorSetLayoutBinding *binding = &bindings[num_bindings];
705       binding->binding = 0;
706       binding->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
707       binding->descriptorCount = 1;
708       binding->stageFlags = stage_flags;
709       binding->pImmutableSamplers = NULL;
710       struct zink_descriptor_template *entry = &shader->precompile.db_template[num_bindings];
711       entry->count = 1;
712       entry->offset = offsetof(struct zink_context, di.db.ubos[clamp_stage(&shader->info)][0]);
713       entry->stride = sizeof(VkDescriptorAddressInfoEXT);
714       entry->db_size = screen->info.db_props.robustUniformBufferDescriptorSize;
715       num_bindings++;
716    }
717    /* sync with zink_shader_compile_separate() */
718    unsigned offsets[4];
719    zink_descriptor_shader_get_binding_offsets(shader, offsets);
720    for (int j = 0; j < ZINK_DESCRIPTOR_BASE_TYPES; j++) {
721       for (int k = 0; k < shader->num_bindings[j]; k++) {
722          VkDescriptorSetLayoutBinding *binding = &bindings[num_bindings];
723          if (j == ZINK_DESCRIPTOR_TYPE_UBO)
724             binding->binding = 1;
725          else
726             binding->binding = shader->bindings[j][k].binding + offsets[j];
727          binding->descriptorType = shader->bindings[j][k].type;
728          binding->descriptorCount = shader->bindings[j][k].size;
729          binding->stageFlags = stage_flags;
730          binding->pImmutableSamplers = NULL;
731 
732          unsigned temp = 0;
733          init_db_template_entry(screen, shader, j, k, &shader->precompile.db_template[num_bindings], &temp);
734          num_bindings++;
735       }
736    }
737    if (num_bindings) {
738       shader->precompile.dsl = descriptor_layout_create(screen, 0, bindings, num_bindings);
739       shader->precompile.bindings = mem_dup(bindings, num_bindings * sizeof(VkDescriptorSetLayoutBinding));
740       shader->precompile.num_bindings = num_bindings;
741       VkDeviceSize val;
742       VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, shader->precompile.dsl, &val);
743       shader->precompile.db_size = align64(val, screen->info.db_props.descriptorBufferOffsetAlignment);
744       shader->precompile.db_offset = rzalloc_array(shader, uint32_t, num_bindings);
745       for (unsigned i = 0; i < num_bindings; i++) {
746          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, shader->precompile.dsl, bindings[i].binding, &val);
747          shader->precompile.db_offset[i] = val;
748       }
749    }
750    if (screen->info.have_EXT_shader_object)
751       return;
752    VkDescriptorSetLayout dsl[ZINK_DESCRIPTOR_ALL_TYPES] = {0};
753    unsigned num_dsl = num_bindings ? 2 : 0;
754    if (shader->bindless)
755       num_dsl = screen->compact_descriptors ? ZINK_DESCRIPTOR_ALL_TYPES - ZINK_DESCRIPTOR_COMPACT : ZINK_DESCRIPTOR_ALL_TYPES;
756    if (num_bindings || shader->bindless) {
757       dsl[shader->info.stage == MESA_SHADER_FRAGMENT] = shader->precompile.dsl;
758       if (shader->bindless)
759          dsl[screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS]] = screen->bindless_layout;
760    }
761    shader->precompile.layout = zink_pipeline_layout_create(screen, dsl, num_dsl, false, VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
762 }
763 
764 void
zink_descriptor_shader_deinit(struct zink_screen * screen,struct zink_shader * shader)765 zink_descriptor_shader_deinit(struct zink_screen *screen, struct zink_shader *shader)
766 {
767    if (shader->precompile.dsl)
768       VKSCR(DestroyDescriptorSetLayout)(screen->dev, shader->precompile.dsl, NULL);
769    if (shader->precompile.layout)
770       VKSCR(DestroyPipelineLayout)(screen->dev, shader->precompile.layout, NULL);
771 }
772 
773 /* called during program destroy */
774 void
zink_descriptor_program_deinit(struct zink_screen * screen,struct zink_program * pg)775 zink_descriptor_program_deinit(struct zink_screen *screen, struct zink_program *pg)
776 {
777    for (unsigned i = 0; pg->num_dsl && i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
778       if (pg->dd.pool_key[i]) {
779          pg->dd.pool_key[i]->use_count--;
780          pg->dd.pool_key[i] = NULL;
781       }
782    }
783    for (unsigned i = 0; pg->num_dsl && i < ZINK_DESCRIPTOR_NON_BINDLESS_TYPES; i++) {
784       if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY && pg->dd.templates[i]) {
785          VKSCR(DestroyDescriptorUpdateTemplate)(screen->dev, pg->dd.templates[i], NULL);
786          pg->dd.templates[i] = VK_NULL_HANDLE;
787       }
788    }
789 }
790 
791 static void
pool_destroy(struct zink_screen * screen,struct zink_descriptor_pool * pool)792 pool_destroy(struct zink_screen *screen, struct zink_descriptor_pool *pool)
793 {
794    VKSCR(DestroyDescriptorPool)(screen->dev, pool->pool, NULL);
795    FREE(pool);
796 }
797 
798 static bool
clear_multi_pool_overflow(struct zink_screen * screen,struct util_dynarray * overflowed_pools)799 clear_multi_pool_overflow(struct zink_screen *screen, struct util_dynarray *overflowed_pools)
800 {
801    bool found = false;
802    while (util_dynarray_num_elements(overflowed_pools, struct zink_descriptor_pool*)) {
803       struct zink_descriptor_pool *pool = util_dynarray_pop(overflowed_pools, struct zink_descriptor_pool*);
804       pool_destroy(screen, pool);
805       found = true;
806    }
807    return found;
808 }
809 
810 static void
deinit_multi_pool_overflow(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)811 deinit_multi_pool_overflow(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
812 {
813    for (unsigned i = 0; i < 2; i++) {
814       clear_multi_pool_overflow(screen, &mpool->overflowed_pools[i]);
815       util_dynarray_fini(&mpool->overflowed_pools[i]);
816    }
817 }
818 
819 static void
multi_pool_destroy(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)820 multi_pool_destroy(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
821 {
822    deinit_multi_pool_overflow(screen, mpool);
823    if (mpool->pool)
824       pool_destroy(screen, mpool->pool);
825    FREE(mpool);
826 }
827 
828 static VkDescriptorPool
create_pool(struct zink_screen * screen,unsigned num_type_sizes,const VkDescriptorPoolSize * sizes,unsigned flags)829 create_pool(struct zink_screen *screen, unsigned num_type_sizes, const VkDescriptorPoolSize *sizes, unsigned flags)
830 {
831    VkDescriptorPool pool;
832    VkDescriptorPoolCreateInfo dpci = {0};
833    dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
834    dpci.pPoolSizes = sizes;
835    dpci.poolSizeCount = num_type_sizes;
836    dpci.flags = flags;
837    dpci.maxSets = MAX_LAZY_DESCRIPTORS;
838    VkResult result;
839    VRAM_ALLOC_LOOP(result,
840       VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &pool),
841       if (result != VK_SUCCESS) {
842          mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result));
843          return VK_NULL_HANDLE;
844       }
845    );
846    return pool;
847 }
848 
849 static struct zink_descriptor_pool *
850 get_descriptor_pool(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute);
851 
852 /* set a multi-pool to its zink_descriptor_pool_key::id-indexed array element on a given batch state */
853 static bool
set_pool(struct zink_batch_state * bs,struct zink_program * pg,struct zink_descriptor_pool_multi * mpool,enum zink_descriptor_type type)854 set_pool(struct zink_batch_state *bs, struct zink_program *pg, struct zink_descriptor_pool_multi *mpool, enum zink_descriptor_type type)
855 {
856    /* push descriptors should never reach this */
857    assert(type != ZINK_DESCRIPTOR_TYPE_UNIFORMS);
858    assert(mpool);
859    const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
860    size_t size = bs->dd.pools[type].capacity;
861    /* ensure the pool array is big enough to have an element for this key */
862    if (!util_dynarray_resize(&bs->dd.pools[type], struct zink_descriptor_pool_multi*, pool_key->id + 1))
863       return false;
864    if (size != bs->dd.pools[type].capacity) {
865       /* when resizing, always zero the new data to avoid garbage */
866       uint8_t *data = bs->dd.pools[type].data;
867       memset(data + size, 0, bs->dd.pools[type].capacity - size);
868    }
869    /* dynarray can't track sparse array sizing, so the array size must be manually tracked */
870    bs->dd.pool_size[type] = MAX2(bs->dd.pool_size[type], pool_key->id + 1);
871    struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi*, pool_key->id);
872    *mppool = mpool;
873    return true;
874 }
875 
876 static struct zink_descriptor_pool *
alloc_new_pool(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)877 alloc_new_pool(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
878 {
879    struct zink_descriptor_pool *pool = CALLOC_STRUCT(zink_descriptor_pool);
880    if (!pool)
881       return NULL;
882    const unsigned num_type_sizes = mpool->pool_key->sizes[1].descriptorCount ? 2 : 1;
883    pool->pool = create_pool(screen, num_type_sizes, mpool->pool_key->sizes, 0);
884    if (!pool->pool) {
885       FREE(pool);
886       return NULL;
887    }
888    return pool;
889 }
890 
891 /* strictly for finding a usable pool in oom scenarios */
892 static void
find_pool(struct zink_screen * screen,struct zink_batch_state * bs,struct zink_descriptor_pool_multi * mpool,bool both)893 find_pool(struct zink_screen *screen, struct zink_batch_state *bs, struct zink_descriptor_pool_multi *mpool, bool both)
894 {
895    bool found = false;
896    /* worst case: iterate all the pools for the batch until something can be recycled */
897    for (unsigned type = 0; type < ZINK_DESCRIPTOR_BASE_TYPES; type++) {
898       for (unsigned i = 0; i < bs->dd.pool_size[type]; i++) {
899          struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi *, i);
900          if (mppool && *mppool && *mppool != mpool) {
901             unsigned idx[] = {!(*mppool)->overflow_idx, (*mppool)->overflow_idx};
902             for (unsigned j = 0; j < 1 + !!both; j++)
903                found |= clear_multi_pool_overflow(screen, &(*mppool)->overflowed_pools[idx[j]]);
904          }
905       }
906    }
907    if (found)
908       mpool->pool = alloc_new_pool(screen, mpool);
909 }
910 
911 static struct zink_descriptor_pool *
check_pool_alloc(struct zink_context * ctx,struct zink_descriptor_pool_multi * mpool,struct zink_program * pg,enum zink_descriptor_type type,struct zink_batch_state * bs,bool is_compute)912 check_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_program *pg,
913                  enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute)
914 {
915    struct zink_screen *screen = zink_screen(ctx->base.screen);
916    assert(mpool->pool_key == pg->dd.pool_key[type]);
917    /* a current pool may not exist */
918    if (!mpool->pool) {
919       /* first, try to recycle a pool from the idle overflowed sets */
920       if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
921          mpool->pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
922       else
923          /* if none exist, try to create a new one */
924          mpool->pool = alloc_new_pool(screen, mpool);
925       /* OOM: force pool recycling from overflows */
926       if (!mpool->pool) {
927          find_pool(screen, bs, mpool, false);
928          if (!mpool->pool) {
929             /* bad case: iterate unused batches and recycle */
930             for (struct zink_batch_state *state = ctx->free_batch_states; state; state = state->next)
931                find_pool(screen, state, mpool, true);
932             if (!mpool->pool) {
933                /* worst case: iterate in-use batches and recycle (very safe) */
934                for (struct zink_batch_state *state = ctx->batch_states; state; state = state->next)
935                   find_pool(screen, state, mpool, false);
936             }
937          }
938       }
939       if (!mpool->pool)
940          unreachable("out of descriptor memory!");
941    }
942    struct zink_descriptor_pool *pool = mpool->pool;
943    /* allocate up to $current * 10, e.g., 10 -> 100;
944     * never allocate more than 100 at a time to minimize unused descriptor sets
945     */
946    if (pool->set_idx == pool->sets_alloc) {
947       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
948       if (!sets_to_alloc) {
949          /* overflowed pool: store for reuse */
950          pool->set_idx = 0;
951          util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
952          mpool->pool = NULL;
953          /* call recursively to get recycle/oom handling */
954          return get_descriptor_pool(ctx, pg, type, bs, is_compute);
955       }
956       if (!zink_descriptor_util_alloc_sets(screen, pg->dsl[type + 1],
957                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc))
958          return NULL;
959       pool->sets_alloc += sets_to_alloc;
960    }
961    return pool;
962 }
963 
964 static struct zink_descriptor_pool *
create_push_pool(struct zink_screen * screen,struct zink_batch_state * bs,bool is_compute,bool has_fbfetch)965 create_push_pool(struct zink_screen *screen, struct zink_batch_state *bs, bool is_compute, bool has_fbfetch)
966 {
967    struct zink_descriptor_pool *pool = CALLOC_STRUCT(zink_descriptor_pool);
968    VkDescriptorPoolSize sizes[2];
969    sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
970    if (is_compute)
971       sizes[0].descriptorCount = MAX_LAZY_DESCRIPTORS;
972    else {
973       sizes[0].descriptorCount = ZINK_GFX_SHADER_COUNT * MAX_LAZY_DESCRIPTORS;
974       sizes[1].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
975       sizes[1].descriptorCount = MAX_LAZY_DESCRIPTORS;
976    }
977    pool->pool = create_pool(screen, !is_compute && has_fbfetch ? 2 : 1, sizes, 0);
978    return pool;
979 }
980 
981 static struct zink_descriptor_pool *
check_push_pool_alloc(struct zink_context * ctx,struct zink_descriptor_pool_multi * mpool,struct zink_batch_state * bs,bool is_compute)982 check_push_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_batch_state *bs, bool is_compute)
983 {
984    struct zink_screen *screen = zink_screen(ctx->base.screen);
985    struct zink_descriptor_pool *pool = mpool->pool;
986    /* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
987    if (pool->set_idx == pool->sets_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
988       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
989       if (!sets_to_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
990          /* overflowed pool: store for reuse */
991          pool->set_idx = 0;
992          util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
993          if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
994             bs->dd.push_pool[is_compute].pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
995          else
996             bs->dd.push_pool[is_compute].pool = create_push_pool(screen, bs, is_compute, ctx->dd.has_fbfetch);
997          if (unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch))
998             mpool->reinit_overflow = true;
999          bs->dd.has_fbfetch = ctx->dd.has_fbfetch;
1000          return check_push_pool_alloc(ctx, &bs->dd.push_pool[is_compute], bs, is_compute);
1001       }
1002       if (!zink_descriptor_util_alloc_sets(screen, ctx->dd.push_dsl[is_compute]->layout,
1003                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc)) {
1004          mesa_loge("ZINK: failed to allocate push set!");
1005          return NULL;
1006       }
1007       pool->sets_alloc += sets_to_alloc;
1008    }
1009    return pool;
1010 }
1011 
1012 static struct zink_descriptor_pool *
get_descriptor_pool(struct zink_context * ctx,struct zink_program * pg,enum zink_descriptor_type type,struct zink_batch_state * bs,bool is_compute)1013 get_descriptor_pool(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute)
1014 {
1015    struct zink_screen *screen = zink_screen(ctx->base.screen);
1016    const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
1017    struct zink_descriptor_pool_multi **mppool = bs->dd.pool_size[type] > pool_key->id ?
1018                                          util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi *, pool_key->id) :
1019                                          NULL;
1020    if (mppool && *mppool)
1021       return check_pool_alloc(ctx, *mppool, pg, type, bs, is_compute);
1022    struct zink_descriptor_pool_multi *mpool = CALLOC_STRUCT(zink_descriptor_pool_multi);
1023    if (!mpool)
1024       return NULL;
1025    util_dynarray_init(&mpool->overflowed_pools[0], NULL);
1026    util_dynarray_init(&mpool->overflowed_pools[1], NULL);
1027    mpool->pool_key = pool_key;
1028    if (!set_pool(bs, pg, mpool, type)) {
1029       multi_pool_destroy(screen, mpool);
1030       return NULL;
1031    }
1032    assert(pool_key->id < bs->dd.pool_size[type]);
1033    return check_pool_alloc(ctx, mpool, pg, type, bs, is_compute);
1034 }
1035 
1036 ALWAYS_INLINE static VkDescriptorSet
get_descriptor_set(struct zink_descriptor_pool * pool)1037 get_descriptor_set(struct zink_descriptor_pool *pool)
1038 {
1039    if (!pool)
1040       return VK_NULL_HANDLE;
1041 
1042    assert(pool->set_idx < pool->sets_alloc);
1043    return pool->sets[pool->set_idx++];
1044 }
1045 
1046 static bool
populate_sets(struct zink_context * ctx,struct zink_batch_state * bs,struct zink_program * pg,uint8_t changed_sets,VkDescriptorSet * sets)1047 populate_sets(struct zink_context *ctx, struct zink_batch_state *bs,
1048               struct zink_program *pg, uint8_t changed_sets, VkDescriptorSet *sets)
1049 {
1050    u_foreach_bit(type, changed_sets) {
1051       if (pg->dd.pool_key[type]) {
1052          struct zink_descriptor_pool *pool = get_descriptor_pool(ctx, pg, type, bs, pg->is_compute);
1053          sets[type] = get_descriptor_set(pool);
1054          if (!sets[type])
1055             return false;
1056       } else
1057          sets[type] = VK_NULL_HANDLE;
1058    }
1059    return true;
1060 }
1061 
1062 static void
reinit_db(struct zink_screen * screen,struct zink_batch_state * bs)1063 reinit_db(struct zink_screen *screen, struct zink_batch_state *bs)
1064 {
1065    zink_batch_descriptor_deinit(screen, bs);
1066    zink_batch_descriptor_init(screen, bs);
1067 }
1068 
1069 static void
enlarge_db(struct zink_context * ctx)1070 enlarge_db(struct zink_context *ctx)
1071 {
1072    struct zink_screen *screen = zink_screen(ctx->base.screen);
1073    struct zink_batch_state *bs = ctx->bs;
1074    /* ensure current db surives */
1075    zink_batch_reference_resource(ctx, bs->dd.db);
1076    /* rebinding a db mid-batch is extremely costly: if we start with a factor
1077     * 16 and then half the factor with each new allocation. It shouldn't need to
1078     * do this more than twice. */
1079    ctx->dd.db.max_db_size *= ctx->dd.db.size_enlarge_scale;
1080    ctx->dd.db.size_enlarge_scale = MAX2(ctx->dd.db.size_enlarge_scale >> 1, 4);
1081    reinit_db(screen, bs);
1082 }
1083 
1084 static void
update_separable(struct zink_context * ctx,struct zink_program * pg)1085 update_separable(struct zink_context *ctx, struct zink_program *pg)
1086 {
1087    struct zink_screen *screen = zink_screen(ctx->base.screen);
1088    struct zink_batch_state *bs = ctx->bs;
1089 
1090    unsigned use_buffer = 0;
1091    VkDescriptorGetInfoEXT info;
1092    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1093    info.pNext = NULL;
1094    struct zink_gfx_program *prog = (struct zink_gfx_program *)pg;
1095    size_t db_size = 0;
1096    for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1097       if (prog->shaders[i])
1098          db_size += prog->shaders[i]->precompile.db_size;
1099    }
1100 
1101    if (bs->dd.db_offset + db_size >= bs->dd.db->base.b.width0)
1102       enlarge_db(ctx);
1103 
1104    if (!bs->dd.db_bound)
1105       zink_batch_bind_db(ctx);
1106 
1107    for (unsigned j = 0; j < ZINK_GFX_SHADER_COUNT; j++) {
1108       struct zink_shader *zs = prog->shaders[j];
1109       if (!zs || !zs->precompile.dsl)
1110          continue;
1111       uint64_t offset = bs->dd.db_offset;
1112       assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + zs->precompile.db_size);
1113       for (unsigned i = 0; i < zs->precompile.num_bindings; i++) {
1114          info.type = zs->precompile.bindings[i].descriptorType;
1115          uint64_t desc_offset = offset + zs->precompile.db_offset[i];
1116          if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray ||
1117                zs->precompile.bindings[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1118                zs->precompile.bindings[i].descriptorCount == 1) {
1119             for (unsigned k = 0; k < zs->precompile.bindings[i].descriptorCount; k++) {
1120                /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1121                info.data.pSampler = (void*)(((uint8_t*)ctx) + zs->precompile.db_template[i].offset + k * zs->precompile.db_template[i].stride);
1122                VKSCR(GetDescriptorEXT)(screen->dev, &info, zs->precompile.db_template[i].db_size, bs->dd.db_map + desc_offset + k * zs->precompile.db_template[i].db_size);
1123             }
1124          } else {
1125             assert(zs->precompile.bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1126             char buf[1024];
1127             uint8_t *db = bs->dd.db_map + desc_offset;
1128             uint8_t *samplers = db + zs->precompile.bindings[i].descriptorCount * screen->info.db_props.sampledImageDescriptorSize;
1129             for (unsigned k = 0; k < zs->precompile.bindings[i].descriptorCount; k++) {
1130                /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1131                info.data.pSampler = (void*)(((uint8_t*)ctx) + zs->precompile.db_template[i].offset +
1132                                              k * zs->precompile.db_template[i].stride);
1133                VKSCR(GetDescriptorEXT)(screen->dev, &info, zs->precompile.db_template[i].db_size, buf);
1134                /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1135                   *
1136                   *   | array_of_samplers[] | array_of_sampled_images[] |
1137                   *
1138                   * which means each descriptor's data must be split
1139                   */
1140                memcpy(db, buf, screen->info.db_props.samplerDescriptorSize);
1141                memcpy(samplers, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize);
1142                db += screen->info.db_props.sampledImageDescriptorSize;
1143                samplers += screen->info.db_props.samplerDescriptorSize;
1144             }
1145          }
1146       }
1147       bs->dd.cur_db_offset[use_buffer] = bs->dd.db_offset;
1148       bs->dd.db_offset += zs->precompile.db_size;
1149 
1150       /* TODO: maybe compile multiple variants for different set counts for compact mode? */
1151       int set_idx = screen->info.have_EXT_shader_object ? j : j == MESA_SHADER_FRAGMENT;
1152       VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pg->layout, set_idx, 1, &use_buffer, &offset);
1153    }
1154 }
1155 
1156 /* updates the mask of changed_sets and binds the mask of bind_sets */
1157 static void
zink_descriptors_update_masked_buffer(struct zink_context * ctx,bool is_compute,uint8_t changed_sets,uint8_t bind_sets)1158 zink_descriptors_update_masked_buffer(struct zink_context *ctx, bool is_compute, uint8_t changed_sets, uint8_t bind_sets)
1159 {
1160    struct zink_screen *screen = zink_screen(ctx->base.screen);
1161    struct zink_batch_state *bs = ctx->bs;
1162    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1163 
1164    /* skip if no descriptors are updated */
1165    if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
1166       return;
1167 
1168    unsigned use_buffer = 0;
1169    u_foreach_bit(type, changed_sets | bind_sets) {
1170       if (!pg->dd.pool_key[type])
1171          continue;
1172       assert(type + 1 < pg->num_dsl);
1173       assert(type < ZINK_DESCRIPTOR_BASE_TYPES);
1174       bool changed = (changed_sets & BITFIELD_BIT(type)) > 0;
1175       uint64_t offset = changed ? bs->dd.db_offset : bs->dd.cur_db_offset[type];
1176       if (pg->dd.db_template[type] && changed) {
1177          const struct zink_descriptor_layout_key *key = pg->dd.pool_key[type]->layout;
1178          VkDescriptorGetInfoEXT info;
1179          info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1180          info.pNext = NULL;
1181          assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + pg->dd.db_size[type]);
1182          for (unsigned i = 0; i < key->num_bindings; i++) {
1183             info.type = key->bindings[i].descriptorType;
1184             uint64_t desc_offset = offset + pg->dd.db_offset[type][i];
1185             if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray ||
1186                 key->bindings[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1187                 key->bindings[i].descriptorCount == 1) {
1188                for (unsigned j = 0; j < key->bindings[i].descriptorCount; j++) {
1189                   /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1190                   info.data.pSampler = (void*)(((uint8_t*)ctx) + pg->dd.db_template[type][i].offset + j * pg->dd.db_template[type][i].stride);
1191                   VKSCR(GetDescriptorEXT)(screen->dev, &info, pg->dd.db_template[type][i].db_size, bs->dd.db_map + desc_offset + j * pg->dd.db_template[type][i].db_size);
1192                }
1193             } else {
1194                assert(key->bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1195                char buf[1024];
1196                uint8_t *db = bs->dd.db_map + desc_offset;
1197                uint8_t *samplers = db + key->bindings[i].descriptorCount * screen->info.db_props.sampledImageDescriptorSize;
1198                for (unsigned j = 0; j < key->bindings[i].descriptorCount; j++) {
1199                   /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1200                   info.data.pSampler = (void*)(((uint8_t*)ctx) + pg->dd.db_template[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][i].offset +
1201                                                j * pg->dd.db_template[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][i].stride);
1202                   VKSCR(GetDescriptorEXT)(screen->dev, &info, pg->dd.db_template[type][ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW].db_size, buf);
1203                   /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1204                    *
1205                    *   | array_of_samplers[] | array_of_sampled_images[] |
1206                    *
1207                    * which means each descriptor's data must be split
1208                    */
1209                   memcpy(db, buf, screen->info.db_props.samplerDescriptorSize);
1210                   memcpy(samplers, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize);
1211                   db += screen->info.db_props.sampledImageDescriptorSize;
1212                   samplers += screen->info.db_props.samplerDescriptorSize;
1213                }
1214             }
1215          }
1216          bs->dd.cur_db_offset[type] = bs->dd.db_offset;
1217          bs->dd.db_offset += pg->dd.db_size[type];
1218       }
1219       /* templates are indexed by the set id, so increment type by 1
1220          * (this is effectively an optimization of indirecting through screen->desc_set_id)
1221          */
1222       VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1223                                                 is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1224                                                 pg->layout,
1225                                                 type + 1, 1,
1226                                                 &use_buffer,
1227                                                 &offset);
1228    }
1229 }
1230 
1231 /* updates the mask of changed_sets and binds the mask of bind_sets */
1232 void
zink_descriptors_update_masked(struct zink_context * ctx,bool is_compute,uint8_t changed_sets,uint8_t bind_sets)1233 zink_descriptors_update_masked(struct zink_context *ctx, bool is_compute, uint8_t changed_sets, uint8_t bind_sets)
1234 {
1235    struct zink_screen *screen = zink_screen(ctx->base.screen);
1236    struct zink_batch_state *bs = ctx->bs;
1237    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1238    VkDescriptorSet desc_sets[ZINK_DESCRIPTOR_BASE_TYPES];
1239 
1240    /* skip if no descriptors are updated */
1241    if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
1242       return;
1243 
1244    /* populate usable sets for the changed_sets mask */
1245    if (!populate_sets(ctx, bs, pg, changed_sets, desc_sets)) {
1246       debug_printf("ZINK: couldn't get descriptor sets!\n");
1247       return;
1248    }
1249    /* no flushing allowed: sets are allocated to the batch, so this breaks everything */
1250    assert(ctx->bs == bs);
1251 
1252    u_foreach_bit(type, changed_sets) {
1253       assert(type + 1 < pg->num_dsl);
1254       if (pg->dd.pool_key[type]) {
1255          /* templates are indexed by the set id, so increment type by 1
1256           * (this is effectively an optimization of indirecting through screen->desc_set_id)
1257           */
1258          VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[type], pg->dd.templates[type + 1], ctx);
1259          VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
1260                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1261                                  /* same set indexing as above */
1262                                  pg->layout, type + 1, 1, &desc_sets[type],
1263                                  0, NULL);
1264          bs->dd.sets[is_compute][type + 1] = desc_sets[type];
1265       }
1266    }
1267    /* these are the unchanged sets being rebound across pipeline changes when compat_id changes but the set is the same
1268     * also handles binding null sets
1269     */
1270    u_foreach_bit(type, bind_sets & ~changed_sets) {
1271       if (!pg->dd.pool_key[type])
1272          continue;
1273       /* same set indexing as above */
1274       assert(bs->dd.sets[is_compute][type + 1]);
1275       VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
1276                               is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1277                               /* same set indexing as above */
1278                               pg->layout, type + 1, 1, &bs->dd.sets[is_compute][type + 1],
1279                               0, NULL);
1280    }
1281 }
1282 
1283 static void
bind_bindless_db(struct zink_context * ctx,struct zink_program * pg)1284 bind_bindless_db(struct zink_context *ctx, struct zink_program *pg)
1285 {
1286    struct zink_batch_state *bs = ctx->bs;
1287    struct zink_screen *screen = zink_screen(ctx->base.screen);
1288    unsigned index = 1;
1289    VkDeviceSize offset = 0;
1290    VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1291                                            pg->is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1292                                            pg->layout,
1293                                            screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS], 1,
1294                                            &index,
1295                                            &offset);
1296    ctx->dd.bindless_bound = true;
1297 }
1298 
1299 /* entrypoint for all descriptor updating:
1300  * - update push set
1301  * - generate masks for updating other sets
1302  * - always called from driver thread
1303  */
1304 void
zink_descriptors_update(struct zink_context * ctx,bool is_compute)1305 zink_descriptors_update(struct zink_context *ctx, bool is_compute)
1306 {
1307    struct zink_batch_state *bs = ctx->bs;
1308    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1309    struct zink_screen *screen = zink_screen(ctx->base.screen);
1310    bool have_KHR_push_descriptor = screen->info.have_KHR_push_descriptor;
1311 
1312    bool batch_changed = !bs->dd.pg[is_compute];
1313    if (batch_changed) {
1314       /* update all sets and bind null sets */
1315       ctx->dd.state_changed[is_compute] = pg->dd.binding_usage & BITFIELD_MASK(ZINK_DESCRIPTOR_TYPE_UNIFORMS);
1316       ctx->dd.push_state_changed[is_compute] = !!pg->dd.push_usage || ctx->dd.has_fbfetch != bs->dd.has_fbfetch;
1317    }
1318 
1319    if (!is_compute) {
1320       struct zink_gfx_program *prog = (struct zink_gfx_program*)pg;
1321       if (prog->is_separable) {
1322          /* force all descriptors update on next pass: separables use different layouts */
1323          ctx->dd.state_changed[is_compute] = BITFIELD_MASK(ZINK_DESCRIPTOR_TYPE_UNIFORMS);
1324          ctx->dd.push_state_changed[is_compute] = true;
1325          update_separable(ctx, pg);
1326          if (pg->dd.bindless)
1327             bind_bindless_db(ctx, pg);
1328          return;
1329       }
1330    }
1331 
1332    if (pg != bs->dd.pg[is_compute]) {
1333       /* if we don't already know that we have to update all sets,
1334        * check to see if any dsls changed
1335        *
1336        * also always update the dsl pointers on program change
1337        */
1338        for (unsigned i = 0; i < ARRAY_SIZE(bs->dd.dsl[is_compute]); i++) {
1339           /* push set is already detected, start at 1 */
1340           if (bs->dd.dsl[is_compute][i] != pg->dsl[i + 1])
1341              ctx->dd.state_changed[is_compute] |= BITFIELD_BIT(i);
1342           bs->dd.dsl[is_compute][i] = pg->dsl[i + 1];
1343        }
1344        ctx->dd.push_state_changed[is_compute] |= bs->dd.push_usage[is_compute] != pg->dd.push_usage;
1345        bs->dd.push_usage[is_compute] = pg->dd.push_usage;
1346    }
1347 
1348    uint8_t changed_sets = pg->dd.binding_usage & ctx->dd.state_changed[is_compute];
1349    /*
1350     * when binding a pipeline, the pipeline can correctly access any previously bound
1351     * descriptor sets which were bound with compatible pipeline layouts
1352     * VK 14.2.2
1353     */
1354    uint8_t bind_sets = bs->dd.pg[is_compute] && bs->dd.compat_id[is_compute] == pg->compat_id ? 0 : pg->dd.binding_usage;
1355 
1356    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1357       size_t check_size = 0;
1358       if (pg->dd.push_usage && ctx->dd.push_state_changed[is_compute])
1359          check_size += ctx->dd.db_size[is_compute];
1360       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1361          if (changed_sets & BITFIELD_BIT(i))
1362             check_size += pg->dd.db_size[i];
1363       }
1364 
1365       if (bs->dd.db_offset + check_size >= bs->dd.db->base.b.width0) {
1366          enlarge_db(ctx);
1367          changed_sets = pg->dd.binding_usage;
1368          ctx->dd.push_state_changed[is_compute] = true;
1369       }
1370 
1371       if (!bs->dd.db_bound)
1372          zink_batch_bind_db(ctx);
1373    }
1374 
1375    if (pg->dd.push_usage && (ctx->dd.push_state_changed[is_compute] || bind_sets)) {
1376       if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1377          uint32_t index = 0;
1378          uint64_t offset = ctx->dd.push_state_changed[is_compute] ?
1379                            bs->dd.db_offset :
1380                            bs->dd.cur_db_offset[ZINK_DESCRIPTOR_TYPE_UNIFORMS];
1381          if (ctx->dd.push_state_changed[is_compute]) {
1382             assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + ctx->dd.db_size[is_compute]);
1383             for (unsigned i = 0; i < (is_compute ? 1 : ZINK_GFX_SHADER_COUNT); i++) {
1384                VkDescriptorGetInfoEXT info;
1385                info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1386                info.pNext = NULL;
1387                info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1388                info.data.pUniformBuffer = &ctx->di.db.ubos[is_compute ? MESA_SHADER_COMPUTE : i][0];
1389                uint64_t stage_offset = offset + (is_compute ? 0 : ctx->dd.db_offset[i]);
1390                VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.robustUniformBufferDescriptorSize,
1391                                                            bs->dd.db_map + stage_offset);
1392             }
1393             if (!is_compute && ctx->dd.has_fbfetch) {
1394                uint64_t stage_offset = offset + ctx->dd.db_offset[MESA_SHADER_FRAGMENT + 1];
1395                if (pg->dd.fbfetch && screen->info.db_props.inputAttachmentDescriptorSize) {
1396                   /* real fbfetch descriptor */
1397                   VkDescriptorGetInfoEXT info;
1398                   info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1399                   info.pNext = NULL;
1400                   info.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1401                   info.data.pInputAttachmentImage = &ctx->di.fbfetch;
1402                   VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.inputAttachmentDescriptorSize,
1403                                                             bs->dd.db_map + stage_offset);
1404                } else {
1405                   /* reuse cached dummy descriptor */
1406                   memcpy(bs->dd.db_map + stage_offset, ctx->di.fbfetch_db, screen->info.db_props.inputAttachmentDescriptorSize);
1407                }
1408             }
1409             bs->dd.cur_db_offset[ZINK_DESCRIPTOR_TYPE_UNIFORMS] = bs->dd.db_offset;
1410             bs->dd.db_offset += ctx->dd.db_size[is_compute];
1411          }
1412          VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1413                                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1414                                                  pg->layout,
1415                                                  0, 1,
1416                                                  &index,
1417                                                  &offset);
1418       } else {
1419          if (have_KHR_push_descriptor) {
1420             if (ctx->dd.push_state_changed[is_compute])
1421                VKCTX(CmdPushDescriptorSetWithTemplateKHR)(bs->cmdbuf, pg->dd.templates[0],
1422                                                          pg->layout, 0, ctx);
1423          } else {
1424             if (ctx->dd.push_state_changed[is_compute]) {
1425                struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, &bs->dd.push_pool[pg->is_compute], bs, pg->is_compute);
1426                VkDescriptorSet push_set = get_descriptor_set(pool);
1427                if (!push_set)
1428                   mesa_loge("ZINK: failed to get push descriptor set! prepare to crash!");
1429                VKCTX(UpdateDescriptorSetWithTemplate)(screen->dev, push_set, pg->dd.templates[0], ctx);
1430                bs->dd.sets[is_compute][0] = push_set;
1431             }
1432             assert(bs->dd.sets[is_compute][0]);
1433             VKCTX(CmdBindDescriptorSets)(bs->cmdbuf,
1434                                     is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1435                                     pg->layout, 0, 1, &bs->dd.sets[is_compute][0],
1436                                     0, NULL);
1437          }
1438       }
1439    }
1440    ctx->dd.push_state_changed[is_compute] = false;
1441    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
1442       zink_descriptors_update_masked_buffer(ctx, is_compute, changed_sets, bind_sets);
1443    else
1444       zink_descriptors_update_masked(ctx, is_compute, changed_sets, bind_sets);
1445    /* bindless descriptors are context-based and get updated elsewhere */
1446    if (pg->dd.bindless && unlikely(!ctx->dd.bindless_bound)) {
1447       if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1448          bind_bindless_db(ctx, pg);
1449       } else {
1450          VKCTX(CmdBindDescriptorSets)(ctx->bs->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1451                                     pg->layout, screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS], 1, &ctx->dd.t.bindless_set,
1452                                     0, NULL);
1453       }
1454       ctx->dd.bindless_bound = true;
1455    }
1456    bs->dd.pg[is_compute] = pg;
1457    ctx->dd.pg[is_compute] = pg;
1458    bs->dd.compat_id[is_compute] = pg->compat_id;
1459    ctx->dd.state_changed[is_compute] = 0;
1460 }
1461 
1462 /* called from gallium descriptor change hooks, e.g., set_sampler_views */
1463 void
zink_context_invalidate_descriptor_state(struct zink_context * ctx,gl_shader_stage shader,enum zink_descriptor_type type,unsigned start,unsigned count)1464 zink_context_invalidate_descriptor_state(struct zink_context *ctx, gl_shader_stage shader, enum zink_descriptor_type type, unsigned start, unsigned count)
1465 {
1466    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
1467       ctx->dd.push_state_changed[shader == MESA_SHADER_COMPUTE] = true;
1468    else
1469       ctx->dd.state_changed[shader == MESA_SHADER_COMPUTE] |= BITFIELD_BIT(type);
1470 }
1471 void
zink_context_invalidate_descriptor_state_compact(struct zink_context * ctx,gl_shader_stage shader,enum zink_descriptor_type type,unsigned start,unsigned count)1472 zink_context_invalidate_descriptor_state_compact(struct zink_context *ctx, gl_shader_stage shader, enum zink_descriptor_type type, unsigned start, unsigned count)
1473 {
1474    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
1475       ctx->dd.push_state_changed[shader == MESA_SHADER_COMPUTE] = true;
1476    else {
1477       if (type > ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)
1478          type -= ZINK_DESCRIPTOR_COMPACT;
1479       ctx->dd.state_changed[shader == MESA_SHADER_COMPUTE] |= BITFIELD_BIT(type);
1480    }
1481 }
1482 
1483 /* called during batch state destroy */
1484 void
zink_batch_descriptor_deinit(struct zink_screen * screen,struct zink_batch_state * bs)1485 zink_batch_descriptor_deinit(struct zink_screen *screen, struct zink_batch_state *bs)
1486 {
1487    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1488       for (unsigned j = 0; j < bs->dd.pools[i].capacity / sizeof(struct zink_descriptor_pool_multi *); j++) {
1489          struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[i], struct zink_descriptor_pool_multi *, j);
1490          if (mppool && *mppool)
1491             multi_pool_destroy(screen, *mppool);
1492       }
1493       util_dynarray_fini(&bs->dd.pools[i]);
1494    }
1495    for (unsigned i = 0; i < 2; i++) {
1496       if (bs->dd.push_pool[i].pool)
1497          pool_destroy(screen, bs->dd.push_pool[i].pool);
1498       deinit_multi_pool_overflow(screen, &bs->dd.push_pool[i]);
1499    }
1500 
1501    if (bs->dd.db_xfer)
1502       zink_screen_buffer_unmap(&screen->base, bs->dd.db_xfer);
1503    bs->dd.db_xfer = NULL;
1504    if (bs->dd.db)
1505       screen->base.resource_destroy(&screen->base, &bs->dd.db->base.b);
1506    bs->dd.db = NULL;
1507    bs->dd.db_bound = false;
1508    bs->dd.db_offset = 0;
1509    memset(bs->dd.cur_db_offset, 0, sizeof(bs->dd.cur_db_offset));
1510 }
1511 
1512 /* ensure the idle/usable overflow set array always has as many members as possible by merging both arrays on batch state reset */
1513 static void
consolidate_pool_alloc(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)1514 consolidate_pool_alloc(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
1515 {
1516    unsigned sizes[] = {
1517       util_dynarray_num_elements(&mpool->overflowed_pools[0], struct zink_descriptor_pool*),
1518       util_dynarray_num_elements(&mpool->overflowed_pools[1], struct zink_descriptor_pool*),
1519    };
1520    if (!sizes[0] && !sizes[1])
1521       return;
1522    /* set idx to whichever overflow is smaller */
1523    mpool->overflow_idx = sizes[0] > sizes[1];
1524    if (!mpool->overflowed_pools[mpool->overflow_idx].size)
1525       return;
1526 
1527    /* attempt to consolidate all the overflow into one array to maximize reuse */
1528    util_dynarray_append_dynarray(&mpool->overflowed_pools[!mpool->overflow_idx], &mpool->overflowed_pools[mpool->overflow_idx]);
1529    util_dynarray_clear(&mpool->overflowed_pools[mpool->overflow_idx]);
1530 }
1531 
1532 /* called when a batch state is reset, i.e., just before a batch state becomes the current state */
1533 void
zink_batch_descriptor_reset(struct zink_screen * screen,struct zink_batch_state * bs)1534 zink_batch_descriptor_reset(struct zink_screen *screen, struct zink_batch_state *bs)
1535 {
1536    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1537       bs->dd.db_offset = 0;
1538       if (bs->dd.db && bs->dd.db->base.b.width0 < bs->ctx->dd.db.max_db_size * screen->base_descriptor_size)
1539          reinit_db(screen, bs);
1540       bs->dd.db_bound = false;
1541    } else {
1542       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1543          struct zink_descriptor_pool_multi **mpools = bs->dd.pools[i].data;
1544          for (unsigned j = 0; j < bs->dd.pool_size[i]; j++) {
1545             struct zink_descriptor_pool_multi *mpool = mpools[j];
1546             if (!mpool)
1547                continue;
1548             consolidate_pool_alloc(screen, mpool);
1549 
1550             /* if the pool is still in use, reset the current set index */
1551             if (mpool->pool_key->use_count)
1552                mpool->pool->set_idx = 0;
1553             else {
1554                /* otherwise destroy it to reclaim memory */
1555                multi_pool_destroy(screen, mpool);
1556                mpools[j] = NULL;
1557             }
1558          }
1559       }
1560       for (unsigned i = 0; i < 2; i++) {
1561          if (bs->dd.push_pool[i].reinit_overflow) {
1562             /* these don't match current fbfetch usage and can never be used again */
1563             clear_multi_pool_overflow(screen, &bs->dd.push_pool[i].overflowed_pools[bs->dd.push_pool[i].overflow_idx]);
1564          } else if (bs->dd.push_pool[i].pool) {
1565             consolidate_pool_alloc(screen, &bs->dd.push_pool[i]);
1566          }
1567          if (bs->dd.push_pool[i].pool)
1568             bs->dd.push_pool[i].pool->set_idx = 0;
1569       }
1570    }
1571    memset(bs->dd.pg, 0, sizeof(bs->dd.pg));
1572 }
1573 
1574 /* called on batch state creation */
1575 bool
zink_batch_descriptor_init(struct zink_screen * screen,struct zink_batch_state * bs)1576 zink_batch_descriptor_init(struct zink_screen *screen, struct zink_batch_state *bs)
1577 {
1578    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
1579       util_dynarray_init(&bs->dd.pools[i], bs);
1580    if (!screen->info.have_KHR_push_descriptor) {
1581       for (unsigned i = 0; i < 2; i++) {
1582          bs->dd.push_pool[i].pool = create_push_pool(screen, bs, i, false);
1583          util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[0], bs);
1584          util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[1], bs);
1585       }
1586    }
1587 
1588    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && !(bs->ctx->flags & ZINK_CONTEXT_COPY_ONLY)) {
1589       unsigned bind = ZINK_BIND_DESCRIPTOR;
1590       struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, bs->ctx->dd.db.max_db_size * screen->base_descriptor_size);
1591       if (!pres)
1592          return false;
1593       bs->dd.db = zink_resource(pres);
1594       bs->dd.db_map = pipe_buffer_map(&bs->ctx->base, pres, PIPE_MAP_READ | PIPE_MAP_WRITE | PIPE_MAP_PERSISTENT | PIPE_MAP_COHERENT | PIPE_MAP_THREAD_SAFE, &bs->dd.db_xfer);
1595    }
1596    return true;
1597 }
1598 
1599 static void
init_push_template_entry(VkDescriptorUpdateTemplateEntry * entry,unsigned i)1600 init_push_template_entry(VkDescriptorUpdateTemplateEntry *entry, unsigned i)
1601 {
1602    entry->dstBinding = i;
1603    entry->descriptorCount = 1;
1604    entry->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1605    entry->offset = offsetof(struct zink_context, di.t.ubos[i][0]);
1606    entry->stride = sizeof(VkDescriptorBufferInfo);
1607 }
1608 
1609 /* called on context creation */
1610 bool
zink_descriptors_init(struct zink_context * ctx)1611 zink_descriptors_init(struct zink_context *ctx)
1612 {
1613    struct zink_screen *screen = zink_screen(ctx->base.screen);
1614    for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1615       VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[i];
1616       init_push_template_entry(entry, i);
1617    }
1618    init_push_template_entry(&ctx->dd.compute_push_entry, MESA_SHADER_COMPUTE);
1619    VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[ZINK_GFX_SHADER_COUNT]; //fbfetch
1620    entry->dstBinding = ZINK_FBFETCH_BINDING;
1621    entry->descriptorCount = 1;
1622    entry->descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1623    entry->offset = offsetof(struct zink_context, di.fbfetch);
1624    entry->stride = sizeof(VkDescriptorImageInfo);
1625    struct zink_descriptor_layout_key *layout_key;
1626    if (!zink_descriptor_util_push_layouts_get(ctx, ctx->dd.push_dsl, ctx->dd.push_layout_keys))
1627       return false;
1628 
1629    ctx->dd.dummy_dsl = descriptor_util_layout_get(screen, 0, NULL, 0, &layout_key);
1630    if (!ctx->dd.dummy_dsl)
1631       return false;
1632 
1633    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1634       VkDeviceSize val;
1635       for (unsigned i = 0; i < 2; i++) {
1636          VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.push_dsl[i]->layout, &val);
1637          ctx->dd.db_size[i] = align64(val, screen->info.db_props.descriptorBufferOffsetAlignment);
1638       }
1639       for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1640          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, i, &val);
1641          ctx->dd.db_offset[i] = val;
1642       }
1643       /* start small */
1644       ctx->dd.db.max_db_size = 250;
1645       ctx->dd.db.size_enlarge_scale = 16;
1646    }
1647 
1648    return true;
1649 }
1650 
1651 /* called on context destroy */
1652 void
zink_descriptors_deinit(struct zink_context * ctx)1653 zink_descriptors_deinit(struct zink_context *ctx)
1654 {
1655    struct zink_screen *screen = zink_screen(ctx->base.screen);
1656    if (ctx->dd.push_dsl[0])
1657       VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[0]->layout, NULL);
1658    if (ctx->dd.push_dsl[1])
1659       VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[1]->layout, NULL);
1660 }
1661 
1662 /* called on screen creation */
1663 bool
zink_descriptor_layouts_init(struct zink_screen * screen)1664 zink_descriptor_layouts_init(struct zink_screen *screen)
1665 {
1666    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1667       if (!_mesa_hash_table_init(&screen->desc_set_layouts[i], screen, hash_descriptor_layout, equals_descriptor_layout))
1668          return false;
1669       if (!_mesa_set_init(&screen->desc_pool_keys[i], screen, hash_descriptor_pool_key, equals_descriptor_pool_key))
1670          return false;
1671    }
1672    simple_mtx_init(&screen->desc_set_layouts_lock, mtx_plain);
1673    simple_mtx_init(&screen->desc_pool_keys_lock, mtx_plain);
1674    return true;
1675 }
1676 
1677 /* called on screen destroy */
1678 void
zink_descriptor_layouts_deinit(struct zink_screen * screen)1679 zink_descriptor_layouts_deinit(struct zink_screen *screen)
1680 {
1681    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1682       hash_table_foreach(&screen->desc_set_layouts[i], he) {
1683          struct zink_descriptor_layout *layout = he->data;
1684          VKSCR(DestroyDescriptorSetLayout)(screen->dev, layout->layout, NULL);
1685          ralloc_free(layout);
1686          _mesa_hash_table_remove(&screen->desc_set_layouts[i], he);
1687       }
1688    }
1689    simple_mtx_destroy(&screen->desc_set_layouts_lock);
1690    simple_mtx_destroy(&screen->desc_pool_keys_lock);
1691 }
1692 
1693 /* fbfetch descriptor is not initialized by default since it is seldom used
1694  * once it is needed, new push layouts/sets are allocated and all previous layouts/sets are destroyed
1695  */
1696 void
zink_descriptor_util_init_fbfetch(struct zink_context * ctx)1697 zink_descriptor_util_init_fbfetch(struct zink_context *ctx)
1698 {
1699    if (ctx->dd.has_fbfetch)
1700       return;
1701 
1702    struct zink_screen *screen = zink_screen(ctx->base.screen);
1703    VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[0]->layout, NULL);
1704    //don't free these now, let ralloc free on teardown to avoid invalid access
1705    //ralloc_free(ctx->dd.push_dsl[0]);
1706    //ralloc_free(ctx->dd.push_layout_keys[0]);
1707    ctx->dd.push_dsl[0] = create_gfx_layout(ctx, &ctx->dd.push_layout_keys[0], true);
1708    ctx->dd.has_fbfetch = true;
1709 
1710    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1711       VkDeviceSize val;
1712       VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, &val);
1713       ctx->dd.db_size[0] = align64(val, screen->info.db_props.descriptorBufferOffsetAlignment);
1714       for (unsigned i = 0; i < ARRAY_SIZE(ctx->dd.db_offset); i++) {
1715          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, i, &val);
1716          ctx->dd.db_offset[i] = val;
1717       }
1718    }
1719 }
1720 
1721 /* called when a shader that uses bindless is created */
1722 void
zink_descriptors_init_bindless(struct zink_context * ctx)1723 zink_descriptors_init_bindless(struct zink_context *ctx)
1724 {
1725    if (ctx->dd.bindless_init)
1726       return;
1727    struct zink_screen *screen = zink_screen(ctx->base.screen);
1728    assert(screen->bindless_layout);
1729    ctx->dd.bindless_init = true;
1730 
1731    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1732       unsigned bind = ZINK_BIND_DESCRIPTOR;
1733       VkDeviceSize size;
1734       VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, screen->bindless_layout, &size);
1735       struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, size);
1736       ctx->dd.db.bindless_db = zink_resource(pres);
1737       ctx->dd.db.bindless_db_map = pipe_buffer_map(&ctx->base, pres, PIPE_MAP_READ | PIPE_MAP_WRITE | PIPE_MAP_PERSISTENT, &ctx->dd.db.bindless_db_xfer);
1738       zink_batch_bind_db(ctx);
1739       for (unsigned i = 0; i < 4; i++) {
1740          VkDeviceSize offset;
1741          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, screen->bindless_layout, i, &offset);
1742          ctx->dd.db.bindless_db_offsets[i] = offset;
1743       }
1744    } else {
1745       VkDescriptorPoolCreateInfo dpci = {0};
1746       VkDescriptorPoolSize sizes[4];
1747       for (unsigned i = 0; i < 4; i++) {
1748          sizes[i].type = zink_descriptor_type_from_bindless_index(i);
1749          sizes[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES;
1750       }
1751       dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1752       dpci.pPoolSizes = sizes;
1753       dpci.poolSizeCount = 4;
1754       dpci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
1755       dpci.maxSets = 1;
1756       VkResult result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &ctx->dd.t.bindless_pool);
1757       if (result != VK_SUCCESS) {
1758          mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result));
1759          return;
1760       }
1761 
1762       zink_descriptor_util_alloc_sets(screen, screen->bindless_layout, ctx->dd.t.bindless_pool, &ctx->dd.t.bindless_set, 1);
1763    }
1764 }
1765 
1766 /* called on context destroy */
1767 void
zink_descriptors_deinit_bindless(struct zink_context * ctx)1768 zink_descriptors_deinit_bindless(struct zink_context *ctx)
1769 {
1770    struct zink_screen *screen = zink_screen(ctx->base.screen);
1771    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1772       if (ctx->dd.db.bindless_db_xfer)
1773          pipe_buffer_unmap(&ctx->base, ctx->dd.db.bindless_db_xfer);
1774       if (ctx->dd.db.bindless_db) {
1775          struct pipe_resource *pres = &ctx->dd.db.bindless_db->base.b;
1776          pipe_resource_reference(&pres, NULL);
1777       }
1778    } else {
1779       if (ctx->dd.t.bindless_pool)
1780          VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd.t.bindless_pool, NULL);
1781    }
1782 }
1783 
1784 /* entrypoint for updating bindless descriptors: called from draw/dispatch */
1785 void
zink_descriptors_update_bindless(struct zink_context * ctx)1786 zink_descriptors_update_bindless(struct zink_context *ctx)
1787 {
1788    struct zink_screen *screen = zink_screen(ctx->base.screen);
1789    VkDescriptorGetInfoEXT info;
1790    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1791    info.pNext = NULL;
1792    /* bindless descriptors are split between images and buffers */
1793    for (unsigned i = 0; i < 2; i++) {
1794       if (!ctx->di.bindless_dirty[i])
1795          continue;
1796       while (util_dynarray_contains(&ctx->di.bindless[i].updates, uint32_t)) {
1797          /* updates are tracked by handle */
1798          uint32_t handle = util_dynarray_pop(&ctx->di.bindless[i].updates, uint32_t);
1799          bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
1800          unsigned binding = i * 2 + !!is_buffer;
1801          if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1802             if (is_buffer) {
1803                size_t size = i ? screen->info.db_props.robustStorageTexelBufferDescriptorSize : screen->info.db_props.robustUniformTexelBufferDescriptorSize;
1804                info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
1805                info.data.pSampler = (void*)&ctx->di.bindless[i].db.buffer_infos[handle - ZINK_MAX_BINDLESS_HANDLES];
1806                VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + handle * size);
1807             } else {
1808                info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1809                if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray || i) {
1810                   size_t size = i ? screen->info.db_props.storageImageDescriptorSize : screen->info.db_props.combinedImageSamplerDescriptorSize;
1811                   info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle];
1812                   VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + handle * size);
1813                } else {
1814                   /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1815                    *
1816                    *   | array_of_samplers[] | array_of_sampled_images[] |
1817                    *
1818                    * which means each descriptor's data must be split
1819                    */
1820                   uint8_t buf[1024];
1821                   size_t size = screen->info.db_props.combinedImageSamplerDescriptorSize;
1822                   info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle];
1823                   VKSCR(GetDescriptorEXT)(screen->dev, &info, size, buf);
1824                   memcpy(ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + handle * screen->info.db_props.samplerDescriptorSize, buf, screen->info.db_props.samplerDescriptorSize);
1825                   size_t offset = screen->info.db_props.samplerDescriptorSize * ZINK_MAX_BINDLESS_HANDLES;
1826                   offset += handle * screen->info.db_props.sampledImageDescriptorSize;
1827                   memcpy(ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + offset, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize);
1828                }
1829             }
1830          } else {
1831             VkWriteDescriptorSet wd;
1832             wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1833             wd.pNext = NULL;
1834             wd.dstSet = ctx->dd.t.bindless_set;
1835             wd.dstBinding = binding;
1836             /* buffer handle ids are offset by ZINK_MAX_BINDLESS_HANDLES for internal tracking */
1837             wd.dstArrayElement = is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle;
1838             wd.descriptorCount = 1;
1839             wd.descriptorType = zink_descriptor_type_from_bindless_index(wd.dstBinding);
1840             if (is_buffer)
1841                wd.pTexelBufferView = &ctx->di.bindless[i].t.buffer_infos[wd.dstArrayElement];
1842             else
1843                wd.pImageInfo = &ctx->di.bindless[i].img_infos[handle];
1844             /* this sucks, but sets must be singly updated to be handled correctly */
1845             VKSCR(UpdateDescriptorSets)(screen->dev, 1, &wd, 0, NULL);
1846          }
1847       }
1848    }
1849    ctx->di.any_bindless_dirty = 0;
1850 }
1851