• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <michael.blumenkrantz@gmail.com>
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] = val;
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 = val;
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 void
multi_pool_destroy(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)799 multi_pool_destroy(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
800 {
801    if (mpool->pool)
802       pool_destroy(screen, mpool->pool);
803    FREE(mpool);
804 }
805 
806 static bool
clear_multi_pool_overflow(struct zink_screen * screen,struct util_dynarray * overflowed_pools)807 clear_multi_pool_overflow(struct zink_screen *screen, struct util_dynarray *overflowed_pools)
808 {
809    bool found = false;
810    while (util_dynarray_num_elements(overflowed_pools, struct zink_descriptor_pool*)) {
811       struct zink_descriptor_pool *pool = util_dynarray_pop(overflowed_pools, struct zink_descriptor_pool*);
812       pool_destroy(screen, pool);
813       found = true;
814    }
815    return found;
816 }
817 
818 static VkDescriptorPool
create_pool(struct zink_screen * screen,unsigned num_type_sizes,const VkDescriptorPoolSize * sizes,unsigned flags)819 create_pool(struct zink_screen *screen, unsigned num_type_sizes, const VkDescriptorPoolSize *sizes, unsigned flags)
820 {
821    VkDescriptorPool pool;
822    VkDescriptorPoolCreateInfo dpci = {0};
823    dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
824    dpci.pPoolSizes = sizes;
825    dpci.poolSizeCount = num_type_sizes;
826    dpci.flags = flags;
827    dpci.maxSets = MAX_LAZY_DESCRIPTORS;
828    VkResult result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &pool);
829    if (result != VK_SUCCESS) {
830       mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result));
831       return VK_NULL_HANDLE;
832    }
833    return pool;
834 }
835 
836 static struct zink_descriptor_pool *
837 get_descriptor_pool(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute);
838 
839 /* set a multi-pool to its zink_descriptor_pool_key::id-indexed array element on a given batch state */
840 static bool
set_pool(struct zink_batch_state * bs,struct zink_program * pg,struct zink_descriptor_pool_multi * mpool,enum zink_descriptor_type type)841 set_pool(struct zink_batch_state *bs, struct zink_program *pg, struct zink_descriptor_pool_multi *mpool, enum zink_descriptor_type type)
842 {
843    /* push descriptors should never reach this */
844    assert(type != ZINK_DESCRIPTOR_TYPE_UNIFORMS);
845    assert(mpool);
846    const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
847    size_t size = bs->dd.pools[type].capacity;
848    /* ensure the pool array is big enough to have an element for this key */
849    if (!util_dynarray_resize(&bs->dd.pools[type], struct zink_descriptor_pool_multi*, pool_key->id + 1))
850       return false;
851    if (size != bs->dd.pools[type].capacity) {
852       /* when resizing, always zero the new data to avoid garbage */
853       uint8_t *data = bs->dd.pools[type].data;
854       memset(data + size, 0, bs->dd.pools[type].capacity - size);
855    }
856    /* dynarray can't track sparse array sizing, so the array size must be manually tracked */
857    bs->dd.pool_size[type] = MAX2(bs->dd.pool_size[type], pool_key->id + 1);
858    struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi*, pool_key->id);
859    *mppool = mpool;
860    return true;
861 }
862 
863 static struct zink_descriptor_pool *
alloc_new_pool(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)864 alloc_new_pool(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
865 {
866    struct zink_descriptor_pool *pool = CALLOC_STRUCT(zink_descriptor_pool);
867    if (!pool)
868       return NULL;
869    const unsigned num_type_sizes = mpool->pool_key->sizes[1].descriptorCount ? 2 : 1;
870    pool->pool = create_pool(screen, num_type_sizes, mpool->pool_key->sizes, 0);
871    if (!pool->pool) {
872       FREE(pool);
873       return NULL;
874    }
875    return pool;
876 }
877 
878 /* strictly for finding a usable pool in oom scenarios */
879 static void
find_pool(struct zink_screen * screen,struct zink_batch_state * bs,struct zink_descriptor_pool_multi * mpool,bool both)880 find_pool(struct zink_screen *screen, struct zink_batch_state *bs, struct zink_descriptor_pool_multi *mpool, bool both)
881 {
882    bool found = false;
883    /* worst case: iterate all the pools for the batch until something can be recycled */
884    for (unsigned type = 0; type < ZINK_DESCRIPTOR_BASE_TYPES; type++) {
885       for (unsigned i = 0; i < bs->dd.pool_size[type]; i++) {
886          struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi *, i);
887          if (mppool && *mppool && *mppool != mpool) {
888             unsigned idx[] = {!(*mppool)->overflow_idx, (*mppool)->overflow_idx};
889             for (unsigned j = 0; j < 1 + !!both; j++)
890                found |= clear_multi_pool_overflow(screen, &(*mppool)->overflowed_pools[idx[j]]);
891          }
892       }
893    }
894    if (found)
895       mpool->pool = alloc_new_pool(screen, mpool);
896 }
897 
898 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)899 check_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_program *pg,
900                  enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute)
901 {
902    struct zink_screen *screen = zink_screen(ctx->base.screen);
903    assert(mpool->pool_key == pg->dd.pool_key[type]);
904    /* a current pool may not exist */
905    if (!mpool->pool) {
906       /* first, try to recycle a pool from the idle overflowed sets */
907       if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
908          mpool->pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
909       else
910          /* if none exist, try to create a new one */
911          mpool->pool = alloc_new_pool(screen, mpool);
912       /* OOM: force pool recycling from overflows */
913       if (!mpool->pool) {
914          find_pool(screen, bs, mpool, false);
915          if (!mpool->pool) {
916             /* bad case: iterate unused batches and recycle */
917             for (struct zink_batch_state *state = ctx->free_batch_states; state; state = state->next)
918                find_pool(screen, state, mpool, true);
919             if (!mpool->pool) {
920                /* worst case: iterate in-use batches and recycle (very safe) */
921                for (struct zink_batch_state *state = ctx->batch_states; state; state = state->next)
922                   find_pool(screen, state, mpool, false);
923             }
924          }
925       }
926       if (!mpool->pool)
927          unreachable("out of descriptor memory!");
928    }
929    struct zink_descriptor_pool *pool = mpool->pool;
930    /* allocate up to $current * 10, e.g., 10 -> 100;
931     * never allocate more than 100 at a time to minimize unused descriptor sets
932     */
933    if (pool->set_idx == pool->sets_alloc) {
934       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
935       if (!sets_to_alloc) {
936          /* overflowed pool: store for reuse */
937          pool->set_idx = 0;
938          util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
939          mpool->pool = NULL;
940          /* call recursively to get recycle/oom handling */
941          return get_descriptor_pool(ctx, pg, type, bs, is_compute);
942       }
943       if (!zink_descriptor_util_alloc_sets(screen, pg->dsl[type + 1],
944                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc))
945          return NULL;
946       pool->sets_alloc += sets_to_alloc;
947    }
948    return pool;
949 }
950 
951 static struct zink_descriptor_pool *
create_push_pool(struct zink_screen * screen,struct zink_batch_state * bs,bool is_compute,bool has_fbfetch)952 create_push_pool(struct zink_screen *screen, struct zink_batch_state *bs, bool is_compute, bool has_fbfetch)
953 {
954    struct zink_descriptor_pool *pool = CALLOC_STRUCT(zink_descriptor_pool);
955    VkDescriptorPoolSize sizes[2];
956    sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
957    if (is_compute)
958       sizes[0].descriptorCount = MAX_LAZY_DESCRIPTORS;
959    else {
960       sizes[0].descriptorCount = ZINK_GFX_SHADER_COUNT * MAX_LAZY_DESCRIPTORS;
961       sizes[1].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
962       sizes[1].descriptorCount = MAX_LAZY_DESCRIPTORS;
963    }
964    pool->pool = create_pool(screen, !is_compute && has_fbfetch ? 2 : 1, sizes, 0);
965    return pool;
966 }
967 
968 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)969 check_push_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_batch_state *bs, bool is_compute)
970 {
971    struct zink_screen *screen = zink_screen(ctx->base.screen);
972    struct zink_descriptor_pool *pool = mpool->pool;
973    /* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
974    if (pool->set_idx == pool->sets_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
975       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
976       if (!sets_to_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
977          /* overflowed pool: store for reuse */
978          pool->set_idx = 0;
979          util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
980          if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
981             bs->dd.push_pool[is_compute].pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
982          else
983             bs->dd.push_pool[is_compute].pool = create_push_pool(screen, bs, is_compute, ctx->dd.has_fbfetch);
984          if (unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch))
985             mpool->reinit_overflow = true;
986          bs->dd.has_fbfetch = ctx->dd.has_fbfetch;
987          return check_push_pool_alloc(ctx, &bs->dd.push_pool[is_compute], bs, is_compute);
988       }
989       if (!zink_descriptor_util_alloc_sets(screen, ctx->dd.push_dsl[is_compute]->layout,
990                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc)) {
991          mesa_loge("ZINK: failed to allocate push set!");
992          return NULL;
993       }
994       pool->sets_alloc += sets_to_alloc;
995    }
996    return pool;
997 }
998 
999 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)1000 get_descriptor_pool(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute)
1001 {
1002    struct zink_screen *screen = zink_screen(ctx->base.screen);
1003    const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
1004    struct zink_descriptor_pool_multi **mppool = bs->dd.pool_size[type] > pool_key->id ?
1005                                          util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi *, pool_key->id) :
1006                                          NULL;
1007    if (mppool && *mppool)
1008       return check_pool_alloc(ctx, *mppool, pg, type, bs, is_compute);
1009    struct zink_descriptor_pool_multi *mpool = CALLOC_STRUCT(zink_descriptor_pool_multi);
1010    if (!mpool)
1011       return NULL;
1012    util_dynarray_init(&mpool->overflowed_pools[0], NULL);
1013    util_dynarray_init(&mpool->overflowed_pools[1], NULL);
1014    mpool->pool_key = pool_key;
1015    if (!set_pool(bs, pg, mpool, type)) {
1016       multi_pool_destroy(screen, mpool);
1017       return NULL;
1018    }
1019    assert(pool_key->id < bs->dd.pool_size[type]);
1020    return check_pool_alloc(ctx, mpool, pg, type, bs, is_compute);
1021 }
1022 
1023 ALWAYS_INLINE static VkDescriptorSet
get_descriptor_set(struct zink_descriptor_pool * pool)1024 get_descriptor_set(struct zink_descriptor_pool *pool)
1025 {
1026    if (!pool)
1027       return VK_NULL_HANDLE;
1028 
1029    assert(pool->set_idx < pool->sets_alloc);
1030    return pool->sets[pool->set_idx++];
1031 }
1032 
1033 static bool
populate_sets(struct zink_context * ctx,struct zink_batch_state * bs,struct zink_program * pg,uint8_t changed_sets,VkDescriptorSet * sets)1034 populate_sets(struct zink_context *ctx, struct zink_batch_state *bs,
1035               struct zink_program *pg, uint8_t changed_sets, VkDescriptorSet *sets)
1036 {
1037    u_foreach_bit(type, changed_sets) {
1038       if (pg->dd.pool_key[type]) {
1039          struct zink_descriptor_pool *pool = get_descriptor_pool(ctx, pg, type, bs, pg->is_compute);
1040          sets[type] = get_descriptor_set(pool);
1041          if (!sets[type])
1042             return false;
1043       } else
1044          sets[type] = VK_NULL_HANDLE;
1045    }
1046    return true;
1047 }
1048 
1049 static void
reinit_db(struct zink_screen * screen,struct zink_batch_state * bs)1050 reinit_db(struct zink_screen *screen, struct zink_batch_state *bs)
1051 {
1052    zink_batch_descriptor_deinit(screen, bs);
1053    zink_batch_descriptor_init(screen, bs);
1054 }
1055 
1056 static void
enlarge_db(struct zink_context * ctx)1057 enlarge_db(struct zink_context *ctx)
1058 {
1059    struct zink_screen *screen = zink_screen(ctx->base.screen);
1060    struct zink_batch_state *bs = ctx->batch.state;
1061    /* ensure current db surives */
1062    zink_batch_reference_resource(&ctx->batch, bs->dd.db);
1063    /* rebinding a db mid-batch is extremely costly: scaling by 10x should ensure it never happens more than twice */
1064    ctx->dd.db.max_db_size *= 10;
1065    reinit_db(screen, bs);
1066 }
1067 
1068 static void
update_separable(struct zink_context * ctx,struct zink_program * pg)1069 update_separable(struct zink_context *ctx, struct zink_program *pg)
1070 {
1071    struct zink_screen *screen = zink_screen(ctx->base.screen);
1072    struct zink_batch_state *bs = ctx->batch.state;
1073 
1074    unsigned use_buffer = 0;
1075    VkDescriptorGetInfoEXT info;
1076    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1077    info.pNext = NULL;
1078    struct zink_gfx_program *prog = (struct zink_gfx_program *)pg;
1079    size_t db_size = 0;
1080    for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1081       if (prog->shaders[i])
1082          db_size += prog->shaders[i]->precompile.db_size;
1083    }
1084 
1085    if (bs->dd.db_offset + db_size >= bs->dd.db->base.b.width0)
1086       enlarge_db(ctx);
1087 
1088    if (!bs->dd.db_bound)
1089       zink_batch_bind_db(ctx);
1090 
1091    for (unsigned j = 0; j < ZINK_GFX_SHADER_COUNT; j++) {
1092       struct zink_shader *zs = prog->shaders[j];
1093       if (!zs || !zs->precompile.dsl)
1094          continue;
1095       uint64_t offset = bs->dd.db_offset;
1096       assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + zs->precompile.db_size);
1097       for (unsigned i = 0; i < zs->precompile.num_bindings; i++) {
1098          info.type = zs->precompile.bindings[i].descriptorType;
1099          uint64_t desc_offset = offset + zs->precompile.db_offset[i];
1100          if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray ||
1101                zs->precompile.bindings[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1102                zs->precompile.bindings[i].descriptorCount == 1) {
1103             for (unsigned k = 0; k < zs->precompile.bindings[i].descriptorCount; k++) {
1104                /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1105                info.data.pSampler = (void*)(((uint8_t*)ctx) + zs->precompile.db_template[i].offset + k * zs->precompile.db_template[i].stride);
1106                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);
1107             }
1108          } else {
1109             assert(zs->precompile.bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1110             char buf[1024];
1111             uint8_t *db = bs->dd.db_map + desc_offset;
1112             uint8_t *samplers = db + zs->precompile.bindings[i].descriptorCount * screen->info.db_props.sampledImageDescriptorSize;
1113             for (unsigned k = 0; k < zs->precompile.bindings[i].descriptorCount; k++) {
1114                /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1115                info.data.pSampler = (void*)(((uint8_t*)ctx) + zs->precompile.db_template[i].offset +
1116                                              k * zs->precompile.db_template[i].stride);
1117                VKSCR(GetDescriptorEXT)(screen->dev, &info, zs->precompile.db_template[i].db_size, buf);
1118                /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1119                   *
1120                   *   | array_of_samplers[] | array_of_sampled_images[] |
1121                   *
1122                   * which means each descriptor's data must be split
1123                   */
1124                memcpy(db, buf, screen->info.db_props.samplerDescriptorSize);
1125                memcpy(samplers, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize);
1126                db += screen->info.db_props.sampledImageDescriptorSize;
1127                samplers += screen->info.db_props.samplerDescriptorSize;
1128             }
1129          }
1130       }
1131       bs->dd.cur_db_offset[use_buffer] = bs->dd.db_offset;
1132       bs->dd.db_offset += zs->precompile.db_size;
1133       /* TODO: maybe compile multiple variants for different set counts for compact mode? */
1134       int set_idx = screen->info.have_EXT_shader_object ? j : j == MESA_SHADER_FRAGMENT;
1135       VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pg->layout, set_idx, 1, &use_buffer, &offset);
1136    }
1137 }
1138 
1139 /* updates the mask of changed_sets and binds the mask of bind_sets */
1140 static void
zink_descriptors_update_masked_buffer(struct zink_context * ctx,bool is_compute,uint8_t changed_sets,uint8_t bind_sets)1141 zink_descriptors_update_masked_buffer(struct zink_context *ctx, bool is_compute, uint8_t changed_sets, uint8_t bind_sets)
1142 {
1143    struct zink_screen *screen = zink_screen(ctx->base.screen);
1144    struct zink_batch_state *bs = ctx->batch.state;
1145    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1146 
1147    /* skip if no descriptors are updated */
1148    if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
1149       return;
1150 
1151    unsigned use_buffer = 0;
1152    u_foreach_bit(type, changed_sets | bind_sets) {
1153       if (!pg->dd.pool_key[type])
1154          continue;
1155       assert(type + 1 < pg->num_dsl);
1156       assert(type < ZINK_DESCRIPTOR_BASE_TYPES);
1157       bool changed = (changed_sets & BITFIELD_BIT(type)) > 0;
1158       uint64_t offset = changed ? bs->dd.db_offset : bs->dd.cur_db_offset[type];
1159       if (pg->dd.db_template[type] && changed) {
1160          const struct zink_descriptor_layout_key *key = pg->dd.pool_key[type]->layout;
1161          VkDescriptorGetInfoEXT info;
1162          info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1163          info.pNext = NULL;
1164          assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + pg->dd.db_size[type]);
1165          for (unsigned i = 0; i < key->num_bindings; i++) {
1166             info.type = key->bindings[i].descriptorType;
1167             uint64_t desc_offset = offset + pg->dd.db_offset[type][i];
1168             if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray ||
1169                 key->bindings[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1170                 key->bindings[i].descriptorCount == 1) {
1171                for (unsigned j = 0; j < key->bindings[i].descriptorCount; j++) {
1172                   /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1173                   info.data.pSampler = (void*)(((uint8_t*)ctx) + pg->dd.db_template[type][i].offset + j * pg->dd.db_template[type][i].stride);
1174                   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);
1175                }
1176             } else {
1177                assert(key->bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1178                char buf[1024];
1179                uint8_t *db = bs->dd.db_map + desc_offset;
1180                uint8_t *samplers = db + key->bindings[i].descriptorCount * screen->info.db_props.sampledImageDescriptorSize;
1181                for (unsigned j = 0; j < key->bindings[i].descriptorCount; j++) {
1182                   /* VkDescriptorDataEXT is a union of pointers; the member doesn't matter */
1183                   info.data.pSampler = (void*)(((uint8_t*)ctx) + pg->dd.db_template[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][i].offset +
1184                                                j * pg->dd.db_template[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][i].stride);
1185                   VKSCR(GetDescriptorEXT)(screen->dev, &info, pg->dd.db_template[type][ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW].db_size, buf);
1186                   /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1187                    *
1188                    *   | array_of_samplers[] | array_of_sampled_images[] |
1189                    *
1190                    * which means each descriptor's data must be split
1191                    */
1192                   memcpy(db, buf, screen->info.db_props.samplerDescriptorSize);
1193                   memcpy(samplers, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize);
1194                   db += screen->info.db_props.sampledImageDescriptorSize;
1195                   samplers += screen->info.db_props.samplerDescriptorSize;
1196                }
1197             }
1198          }
1199          bs->dd.cur_db_offset[type] = bs->dd.db_offset;
1200          bs->dd.db_offset += pg->dd.db_size[type];
1201       }
1202       zink_flush_dgc_if_enabled(ctx);
1203       /* templates are indexed by the set id, so increment type by 1
1204          * (this is effectively an optimization of indirecting through screen->desc_set_id)
1205          */
1206       VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1207                                                 is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1208                                                 pg->layout,
1209                                                 type + 1, 1,
1210                                                 &use_buffer,
1211                                                 &offset);
1212    }
1213 }
1214 
1215 /* updates the mask of changed_sets and binds the mask of bind_sets */
1216 void
zink_descriptors_update_masked(struct zink_context * ctx,bool is_compute,uint8_t changed_sets,uint8_t bind_sets)1217 zink_descriptors_update_masked(struct zink_context *ctx, bool is_compute, uint8_t changed_sets, uint8_t bind_sets)
1218 {
1219    struct zink_screen *screen = zink_screen(ctx->base.screen);
1220    struct zink_batch_state *bs = ctx->batch.state;
1221    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1222    VkDescriptorSet desc_sets[ZINK_DESCRIPTOR_BASE_TYPES];
1223 
1224    /* skip if no descriptors are updated */
1225    if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
1226       return;
1227 
1228    /* populate usable sets for the changed_sets mask */
1229    if (!populate_sets(ctx, bs, pg, changed_sets, desc_sets)) {
1230       debug_printf("ZINK: couldn't get descriptor sets!\n");
1231       return;
1232    }
1233    /* no flushing allowed: sets are allocated to the batch, so this breaks everything */
1234    assert(ctx->batch.state == bs);
1235 
1236    u_foreach_bit(type, changed_sets) {
1237       assert(type + 1 < pg->num_dsl);
1238       if (pg->dd.pool_key[type]) {
1239          zink_flush_dgc_if_enabled(ctx);
1240          /* templates are indexed by the set id, so increment type by 1
1241           * (this is effectively an optimization of indirecting through screen->desc_set_id)
1242           */
1243          VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[type], pg->dd.templates[type + 1], ctx);
1244          VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
1245                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1246                                  /* same set indexing as above */
1247                                  pg->layout, type + 1, 1, &desc_sets[type],
1248                                  0, NULL);
1249          bs->dd.sets[is_compute][type + 1] = desc_sets[type];
1250       }
1251    }
1252    /* these are the unchanged sets being rebound across pipeline changes when compat_id changes but the set is the same
1253     * also handles binding null sets
1254     */
1255    u_foreach_bit(type, bind_sets & ~changed_sets) {
1256       if (!pg->dd.pool_key[type])
1257          continue;
1258       /* same set indexing as above */
1259       assert(bs->dd.sets[is_compute][type + 1]);
1260       zink_flush_dgc_if_enabled(ctx);
1261       VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
1262                               is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1263                               /* same set indexing as above */
1264                               pg->layout, type + 1, 1, &bs->dd.sets[is_compute][type + 1],
1265                               0, NULL);
1266    }
1267 }
1268 
1269 static void
bind_bindless_db(struct zink_context * ctx,struct zink_program * pg)1270 bind_bindless_db(struct zink_context *ctx, struct zink_program *pg)
1271 {
1272    struct zink_batch_state *bs = ctx->batch.state;
1273    struct zink_screen *screen = zink_screen(ctx->base.screen);
1274    unsigned index = 1;
1275    VkDeviceSize offset = 0;
1276    VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1277                                            pg->is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1278                                            pg->layout,
1279                                            screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS], 1,
1280                                            &index,
1281                                            &offset);
1282    ctx->dd.bindless_bound = true;
1283 }
1284 
1285 /* entrypoint for all descriptor updating:
1286  * - update push set
1287  * - generate masks for updating other sets
1288  * - always called from driver thread
1289  */
1290 void
zink_descriptors_update(struct zink_context * ctx,bool is_compute)1291 zink_descriptors_update(struct zink_context *ctx, bool is_compute)
1292 {
1293    struct zink_batch_state *bs = ctx->batch.state;
1294    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
1295    struct zink_screen *screen = zink_screen(ctx->base.screen);
1296    bool have_KHR_push_descriptor = screen->info.have_KHR_push_descriptor;
1297 
1298    bool batch_changed = !bs->dd.pg[is_compute];
1299    if (batch_changed) {
1300       /* update all sets and bind null sets */
1301       ctx->dd.state_changed[is_compute] = pg->dd.binding_usage & BITFIELD_MASK(ZINK_DESCRIPTOR_TYPE_UNIFORMS);
1302       ctx->dd.push_state_changed[is_compute] = !!pg->dd.push_usage || ctx->dd.has_fbfetch != bs->dd.has_fbfetch;
1303    }
1304 
1305    if (!is_compute) {
1306       struct zink_gfx_program *prog = (struct zink_gfx_program*)pg;
1307       if (prog->is_separable) {
1308          /* force all descriptors update on next pass: separables use different layouts */
1309          ctx->dd.state_changed[is_compute] = BITFIELD_MASK(ZINK_DESCRIPTOR_TYPE_UNIFORMS);
1310          ctx->dd.push_state_changed[is_compute] = true;
1311          update_separable(ctx, pg);
1312          if (pg->dd.bindless)
1313             bind_bindless_db(ctx, pg);
1314          return;
1315       }
1316    }
1317 
1318    if (pg != bs->dd.pg[is_compute]) {
1319       /* if we don't already know that we have to update all sets,
1320        * check to see if any dsls changed
1321        *
1322        * also always update the dsl pointers on program change
1323        */
1324        for (unsigned i = 0; i < ARRAY_SIZE(bs->dd.dsl[is_compute]); i++) {
1325           /* push set is already detected, start at 1 */
1326           if (bs->dd.dsl[is_compute][i] != pg->dsl[i + 1])
1327              ctx->dd.state_changed[is_compute] |= BITFIELD_BIT(i);
1328           bs->dd.dsl[is_compute][i] = pg->dsl[i + 1];
1329        }
1330        ctx->dd.push_state_changed[is_compute] |= bs->dd.push_usage[is_compute] != pg->dd.push_usage;
1331        bs->dd.push_usage[is_compute] = pg->dd.push_usage;
1332    }
1333 
1334    uint8_t changed_sets = pg->dd.binding_usage & ctx->dd.state_changed[is_compute];
1335    /*
1336     * when binding a pipeline, the pipeline can correctly access any previously bound
1337     * descriptor sets which were bound with compatible pipeline layouts
1338     * VK 14.2.2
1339     */
1340    uint8_t bind_sets = bs->dd.pg[is_compute] && bs->dd.compat_id[is_compute] == pg->compat_id ? 0 : pg->dd.binding_usage;
1341 
1342    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1343       size_t check_size = 0;
1344       if (pg->dd.push_usage && ctx->dd.push_state_changed[is_compute])
1345          check_size += ctx->dd.db_size[is_compute];
1346       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1347          if (changed_sets & BITFIELD_BIT(i))
1348             check_size += pg->dd.db_size[i];
1349       }
1350 
1351       if (bs->dd.db_offset + check_size >= bs->dd.db->base.b.width0) {
1352          enlarge_db(ctx);
1353          changed_sets = pg->dd.binding_usage;
1354          ctx->dd.push_state_changed[is_compute] = true;
1355          zink_flush_dgc_if_enabled(ctx);
1356       }
1357 
1358       if (!bs->dd.db_bound)
1359          zink_batch_bind_db(ctx);
1360    }
1361 
1362    if (pg->dd.push_usage && (ctx->dd.push_state_changed[is_compute] || bind_sets)) {
1363       if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1364          uint32_t index = 0;
1365          uint64_t offset = ctx->dd.push_state_changed[is_compute] ?
1366                            bs->dd.db_offset :
1367                            bs->dd.cur_db_offset[ZINK_DESCRIPTOR_TYPE_UNIFORMS];
1368          if (ctx->dd.push_state_changed[is_compute]) {
1369             assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + ctx->dd.db_size[is_compute]);
1370             for (unsigned i = 0; i < (is_compute ? 1 : ZINK_GFX_SHADER_COUNT); i++) {
1371                VkDescriptorGetInfoEXT info;
1372                info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1373                info.pNext = NULL;
1374                info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1375                info.data.pUniformBuffer = &ctx->di.db.ubos[is_compute ? MESA_SHADER_COMPUTE : i][0];
1376                uint64_t stage_offset = offset + (is_compute ? 0 : ctx->dd.db_offset[i]);
1377                VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.robustUniformBufferDescriptorSize,
1378                                                            bs->dd.db_map + stage_offset);
1379             }
1380             if (!is_compute && ctx->dd.has_fbfetch) {
1381                uint64_t stage_offset = offset + ctx->dd.db_offset[MESA_SHADER_FRAGMENT + 1];
1382                if (pg->dd.fbfetch && screen->info.db_props.inputAttachmentDescriptorSize) {
1383                   /* real fbfetch descriptor */
1384                   VkDescriptorGetInfoEXT info;
1385                   info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1386                   info.pNext = NULL;
1387                   info.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1388                   info.data.pInputAttachmentImage = &ctx->di.fbfetch;
1389                   VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.inputAttachmentDescriptorSize,
1390                                                             bs->dd.db_map + stage_offset);
1391                } else {
1392                   /* reuse cached dummy descriptor */
1393                   memcpy(bs->dd.db_map + stage_offset, ctx->di.fbfetch_db, screen->info.db_props.inputAttachmentDescriptorSize);
1394                }
1395             }
1396             bs->dd.cur_db_offset[ZINK_DESCRIPTOR_TYPE_UNIFORMS] = bs->dd.db_offset;
1397             bs->dd.db_offset += ctx->dd.db_size[is_compute];
1398          }
1399          zink_flush_dgc_if_enabled(ctx);
1400          VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf,
1401                                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1402                                                  pg->layout,
1403                                                  0, 1,
1404                                                  &index,
1405                                                  &offset);
1406       } else {
1407          if (ctx->dd.push_state_changed[0]) {
1408             zink_flush_dgc_if_enabled(ctx);
1409          }
1410          if (have_KHR_push_descriptor) {
1411             if (ctx->dd.push_state_changed[is_compute])
1412                VKCTX(CmdPushDescriptorSetWithTemplateKHR)(bs->cmdbuf, pg->dd.templates[0],
1413                                                          pg->layout, 0, ctx);
1414          } else {
1415             if (ctx->dd.push_state_changed[is_compute]) {
1416                struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, &bs->dd.push_pool[pg->is_compute], bs, pg->is_compute);
1417                VkDescriptorSet push_set = get_descriptor_set(pool);
1418                if (!push_set)
1419                   mesa_loge("ZINK: failed to get push descriptor set! prepare to crash!");
1420                VKCTX(UpdateDescriptorSetWithTemplate)(screen->dev, push_set, pg->dd.templates[0], ctx);
1421                bs->dd.sets[is_compute][0] = push_set;
1422             }
1423             assert(bs->dd.sets[is_compute][0]);
1424             VKCTX(CmdBindDescriptorSets)(bs->cmdbuf,
1425                                     is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1426                                     pg->layout, 0, 1, &bs->dd.sets[is_compute][0],
1427                                     0, NULL);
1428          }
1429       }
1430    }
1431    ctx->dd.push_state_changed[is_compute] = false;
1432    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
1433       zink_descriptors_update_masked_buffer(ctx, is_compute, changed_sets, bind_sets);
1434    else
1435       zink_descriptors_update_masked(ctx, is_compute, changed_sets, bind_sets);
1436    /* bindless descriptors are context-based and get updated elsewhere */
1437    if (pg->dd.bindless && unlikely(!ctx->dd.bindless_bound)) {
1438       if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1439          bind_bindless_db(ctx, pg);
1440       } else {
1441          VKCTX(CmdBindDescriptorSets)(ctx->batch.state->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
1442                                     pg->layout, screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS], 1, &ctx->dd.t.bindless_set,
1443                                     0, NULL);
1444       }
1445       ctx->dd.bindless_bound = true;
1446    }
1447    bs->dd.pg[is_compute] = pg;
1448    ctx->dd.pg[is_compute] = pg;
1449    bs->dd.compat_id[is_compute] = pg->compat_id;
1450    ctx->dd.state_changed[is_compute] = 0;
1451 }
1452 
1453 /* called from gallium descriptor change hooks, e.g., set_sampler_views */
1454 void
zink_context_invalidate_descriptor_state(struct zink_context * ctx,gl_shader_stage shader,enum zink_descriptor_type type,unsigned start,unsigned count)1455 zink_context_invalidate_descriptor_state(struct zink_context *ctx, gl_shader_stage shader, enum zink_descriptor_type type, unsigned start, unsigned count)
1456 {
1457    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
1458       ctx->dd.push_state_changed[shader == MESA_SHADER_COMPUTE] = true;
1459    else
1460       ctx->dd.state_changed[shader == MESA_SHADER_COMPUTE] |= BITFIELD_BIT(type);
1461 }
1462 void
zink_context_invalidate_descriptor_state_compact(struct zink_context * ctx,gl_shader_stage shader,enum zink_descriptor_type type,unsigned start,unsigned count)1463 zink_context_invalidate_descriptor_state_compact(struct zink_context *ctx, gl_shader_stage shader, enum zink_descriptor_type type, unsigned start, unsigned count)
1464 {
1465    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
1466       ctx->dd.push_state_changed[shader == MESA_SHADER_COMPUTE] = true;
1467    else {
1468       if (type > ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)
1469          type -= ZINK_DESCRIPTOR_COMPACT;
1470       ctx->dd.state_changed[shader == MESA_SHADER_COMPUTE] |= BITFIELD_BIT(type);
1471    }
1472 }
1473 
1474 static void
deinit_multi_pool_overflow(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)1475 deinit_multi_pool_overflow(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
1476 {
1477    for (unsigned i = 0; i < 2; i++) {
1478       clear_multi_pool_overflow(screen, &mpool->overflowed_pools[i]);
1479       util_dynarray_fini(&mpool->overflowed_pools[i]);
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             deinit_multi_pool_overflow(screen, *mppool);
1492             multi_pool_destroy(screen, *mppool);
1493          }
1494       }
1495       util_dynarray_fini(&bs->dd.pools[i]);
1496    }
1497    for (unsigned i = 0; i < 2; i++) {
1498       if (bs->dd.push_pool[i].pool)
1499          pool_destroy(screen, bs->dd.push_pool[i].pool);
1500       deinit_multi_pool_overflow(screen, &bs->dd.push_pool[i]);
1501    }
1502 
1503    if (bs->dd.db_xfer)
1504       zink_screen_buffer_unmap(&screen->base, bs->dd.db_xfer);
1505    bs->dd.db_xfer = NULL;
1506    if (bs->dd.db)
1507       screen->base.resource_destroy(&screen->base, &bs->dd.db->base.b);
1508    bs->dd.db = NULL;
1509    bs->dd.db_bound = false;
1510    bs->dd.db_offset = 0;
1511    memset(bs->dd.cur_db_offset, 0, sizeof(bs->dd.cur_db_offset));
1512 }
1513 
1514 /* ensure the idle/usable overflow set array always has as many members as possible by merging both arrays on batch state reset */
1515 static void
consolidate_pool_alloc(struct zink_screen * screen,struct zink_descriptor_pool_multi * mpool)1516 consolidate_pool_alloc(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
1517 {
1518    unsigned sizes[] = {
1519       util_dynarray_num_elements(&mpool->overflowed_pools[0], struct zink_descriptor_pool*),
1520       util_dynarray_num_elements(&mpool->overflowed_pools[1], struct zink_descriptor_pool*),
1521    };
1522    if (!sizes[0] && !sizes[1])
1523       return;
1524    /* set idx to whichever overflow is smaller */
1525    mpool->overflow_idx = sizes[0] > sizes[1];
1526    if (!mpool->overflowed_pools[mpool->overflow_idx].size)
1527       return;
1528 
1529    /* attempt to consolidate all the overflow into one array to maximize reuse */
1530    util_dynarray_append_dynarray(&mpool->overflowed_pools[!mpool->overflow_idx], &mpool->overflowed_pools[mpool->overflow_idx]);
1531    util_dynarray_clear(&mpool->overflowed_pools[mpool->overflow_idx]);
1532 }
1533 
1534 /* called when a batch state is reset, i.e., just before a batch state becomes the current state */
1535 void
zink_batch_descriptor_reset(struct zink_screen * screen,struct zink_batch_state * bs)1536 zink_batch_descriptor_reset(struct zink_screen *screen, struct zink_batch_state *bs)
1537 {
1538    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1539       bs->dd.db_offset = 0;
1540       if (bs->dd.db && bs->dd.db->base.b.width0 < bs->ctx->dd.db.max_db_size * screen->base_descriptor_size)
1541          reinit_db(screen, bs);
1542       bs->dd.db_bound = false;
1543    } else {
1544       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1545          struct zink_descriptor_pool_multi **mpools = bs->dd.pools[i].data;
1546          for (unsigned j = 0; j < bs->dd.pool_size[i]; j++) {
1547             struct zink_descriptor_pool_multi *mpool = mpools[j];
1548             if (!mpool)
1549                continue;
1550             consolidate_pool_alloc(screen, mpool);
1551 
1552             /* if the pool is still in use, reset the current set index */
1553             if (mpool->pool_key->use_count)
1554                mpool->pool->set_idx = 0;
1555             else {
1556                /* otherwise destroy it to reclaim memory */
1557                multi_pool_destroy(screen, mpool);
1558                mpools[j] = NULL;
1559             }
1560          }
1561       }
1562       for (unsigned i = 0; i < 2; i++) {
1563          if (bs->dd.push_pool[i].reinit_overflow) {
1564             /* these don't match current fbfetch usage and can never be used again */
1565             clear_multi_pool_overflow(screen, &bs->dd.push_pool[i].overflowed_pools[bs->dd.push_pool[i].overflow_idx]);
1566          } else if (bs->dd.push_pool[i].pool) {
1567             consolidate_pool_alloc(screen, &bs->dd.push_pool[i]);
1568          }
1569          if (bs->dd.push_pool[i].pool)
1570             bs->dd.push_pool[i].pool->set_idx = 0;
1571       }
1572    }
1573    memset(bs->dd.pg, 0, sizeof(bs->dd.pg));
1574 }
1575 
1576 /* called on batch state creation */
1577 bool
zink_batch_descriptor_init(struct zink_screen * screen,struct zink_batch_state * bs)1578 zink_batch_descriptor_init(struct zink_screen *screen, struct zink_batch_state *bs)
1579 {
1580    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
1581       util_dynarray_init(&bs->dd.pools[i], bs);
1582    if (!screen->info.have_KHR_push_descriptor) {
1583       for (unsigned i = 0; i < 2; i++) {
1584          bs->dd.push_pool[i].pool = create_push_pool(screen, bs, i, false);
1585          util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[0], bs);
1586          util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[1], bs);
1587       }
1588    }
1589 
1590    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && !(bs->ctx->flags & ZINK_CONTEXT_COPY_ONLY)) {
1591       unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR;
1592       struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, bs->ctx->dd.db.max_db_size * screen->base_descriptor_size);
1593       if (!pres)
1594          return false;
1595       bs->dd.db = zink_resource(pres);
1596       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);
1597    }
1598    return true;
1599 }
1600 
1601 static void
init_push_template_entry(VkDescriptorUpdateTemplateEntry * entry,unsigned i)1602 init_push_template_entry(VkDescriptorUpdateTemplateEntry *entry, unsigned i)
1603 {
1604    entry->dstBinding = i;
1605    entry->descriptorCount = 1;
1606    entry->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1607    entry->offset = offsetof(struct zink_context, di.t.ubos[i][0]);
1608    entry->stride = sizeof(VkDescriptorBufferInfo);
1609 }
1610 
1611 /* called on context creation */
1612 bool
zink_descriptors_init(struct zink_context * ctx)1613 zink_descriptors_init(struct zink_context *ctx)
1614 {
1615    struct zink_screen *screen = zink_screen(ctx->base.screen);
1616    for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1617       VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[i];
1618       init_push_template_entry(entry, i);
1619    }
1620    init_push_template_entry(&ctx->dd.compute_push_entry, MESA_SHADER_COMPUTE);
1621    VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[ZINK_GFX_SHADER_COUNT]; //fbfetch
1622    entry->dstBinding = ZINK_FBFETCH_BINDING;
1623    entry->descriptorCount = 1;
1624    entry->descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1625    entry->offset = offsetof(struct zink_context, di.fbfetch);
1626    entry->stride = sizeof(VkDescriptorImageInfo);
1627    struct zink_descriptor_layout_key *layout_key;
1628    if (!zink_descriptor_util_push_layouts_get(ctx, ctx->dd.push_dsl, ctx->dd.push_layout_keys))
1629       return false;
1630 
1631    ctx->dd.dummy_dsl = descriptor_util_layout_get(screen, 0, NULL, 0, &layout_key);
1632    if (!ctx->dd.dummy_dsl)
1633       return false;
1634 
1635    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1636       VkDeviceSize val;
1637       for (unsigned i = 0; i < 2; i++) {
1638          VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.push_dsl[i]->layout, &val);
1639          ctx->dd.db_size[i] = val;
1640       }
1641       for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
1642          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, i, &val);
1643          ctx->dd.db_offset[i] = val;
1644       }
1645       /* start small */
1646       ctx->dd.db.max_db_size = 250;
1647    }
1648 
1649    return true;
1650 }
1651 
1652 /* called on context destroy */
1653 void
zink_descriptors_deinit(struct zink_context * ctx)1654 zink_descriptors_deinit(struct zink_context *ctx)
1655 {
1656    struct zink_screen *screen = zink_screen(ctx->base.screen);
1657    if (ctx->dd.push_dsl[0])
1658       VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[0]->layout, NULL);
1659    if (ctx->dd.push_dsl[1])
1660       VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[1]->layout, NULL);
1661 }
1662 
1663 /* called on screen creation */
1664 bool
zink_descriptor_layouts_init(struct zink_screen * screen)1665 zink_descriptor_layouts_init(struct zink_screen *screen)
1666 {
1667    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1668       if (!_mesa_hash_table_init(&screen->desc_set_layouts[i], screen, hash_descriptor_layout, equals_descriptor_layout))
1669          return false;
1670       if (!_mesa_set_init(&screen->desc_pool_keys[i], screen, hash_descriptor_pool_key, equals_descriptor_pool_key))
1671          return false;
1672    }
1673    simple_mtx_init(&screen->desc_set_layouts_lock, mtx_plain);
1674    simple_mtx_init(&screen->desc_pool_keys_lock, mtx_plain);
1675    return true;
1676 }
1677 
1678 /* called on screen destroy */
1679 void
zink_descriptor_layouts_deinit(struct zink_screen * screen)1680 zink_descriptor_layouts_deinit(struct zink_screen *screen)
1681 {
1682    for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) {
1683       hash_table_foreach(&screen->desc_set_layouts[i], he) {
1684          struct zink_descriptor_layout *layout = he->data;
1685          VKSCR(DestroyDescriptorSetLayout)(screen->dev, layout->layout, NULL);
1686          ralloc_free(layout);
1687          _mesa_hash_table_remove(&screen->desc_set_layouts[i], he);
1688       }
1689    }
1690    simple_mtx_destroy(&screen->desc_set_layouts_lock);
1691    simple_mtx_destroy(&screen->desc_pool_keys_lock);
1692 }
1693 
1694 /* fbfetch descriptor is not initialized by default since it is seldom used
1695  * once it is needed, new push layouts/sets are allocated and all previous layouts/sets are destroyed
1696  */
1697 void
zink_descriptor_util_init_fbfetch(struct zink_context * ctx)1698 zink_descriptor_util_init_fbfetch(struct zink_context *ctx)
1699 {
1700    if (ctx->dd.has_fbfetch)
1701       return;
1702 
1703    struct zink_screen *screen = zink_screen(ctx->base.screen);
1704    VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.push_dsl[0]->layout, NULL);
1705    //don't free these now, let ralloc free on teardown to avoid invalid access
1706    //ralloc_free(ctx->dd.push_dsl[0]);
1707    //ralloc_free(ctx->dd.push_layout_keys[0]);
1708    ctx->dd.push_dsl[0] = create_gfx_layout(ctx, &ctx->dd.push_layout_keys[0], true);
1709    ctx->dd.has_fbfetch = true;
1710 
1711    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1712       VkDeviceSize val;
1713       VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, &val);
1714       ctx->dd.db_size[0] = val;
1715       for (unsigned i = 0; i < ARRAY_SIZE(ctx->dd.db_offset); i++) {
1716          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, i, &val);
1717          ctx->dd.db_offset[i] = val;
1718       }
1719    }
1720 }
1721 
1722 /* called when a shader that uses bindless is created */
1723 void
zink_descriptors_init_bindless(struct zink_context * ctx)1724 zink_descriptors_init_bindless(struct zink_context *ctx)
1725 {
1726    if (ctx->dd.bindless_init)
1727       return;
1728    struct zink_screen *screen = zink_screen(ctx->base.screen);
1729    assert(screen->bindless_layout);
1730    ctx->dd.bindless_init = true;
1731 
1732    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1733       unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR;
1734       VkDeviceSize size;
1735       VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, screen->bindless_layout, &size);
1736       struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, size);
1737       ctx->dd.db.bindless_db = zink_resource(pres);
1738       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);
1739       zink_batch_bind_db(ctx);
1740       for (unsigned i = 0; i < 4; i++) {
1741          VkDeviceSize offset;
1742          VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, screen->bindless_layout, i, &offset);
1743          ctx->dd.db.bindless_db_offsets[i] = offset;
1744       }
1745    } else {
1746       VkDescriptorPoolCreateInfo dpci = {0};
1747       VkDescriptorPoolSize sizes[4];
1748       for (unsigned i = 0; i < 4; i++) {
1749          sizes[i].type = zink_descriptor_type_from_bindless_index(i);
1750          sizes[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES;
1751       }
1752       dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1753       dpci.pPoolSizes = sizes;
1754       dpci.poolSizeCount = 4;
1755       dpci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
1756       dpci.maxSets = 1;
1757       VkResult result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &ctx->dd.t.bindless_pool);
1758       if (result != VK_SUCCESS) {
1759          mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result));
1760          return;
1761       }
1762 
1763       zink_descriptor_util_alloc_sets(screen, screen->bindless_layout, ctx->dd.t.bindless_pool, &ctx->dd.t.bindless_set, 1);
1764    }
1765 }
1766 
1767 /* called on context destroy */
1768 void
zink_descriptors_deinit_bindless(struct zink_context * ctx)1769 zink_descriptors_deinit_bindless(struct zink_context *ctx)
1770 {
1771    struct zink_screen *screen = zink_screen(ctx->base.screen);
1772    if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1773       if (ctx->dd.db.bindless_db_xfer)
1774          pipe_buffer_unmap(&ctx->base, ctx->dd.db.bindless_db_xfer);
1775       if (ctx->dd.db.bindless_db) {
1776          struct pipe_resource *pres = &ctx->dd.db.bindless_db->base.b;
1777          pipe_resource_reference(&pres, NULL);
1778       }
1779    } else {
1780       if (ctx->dd.t.bindless_pool)
1781          VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd.t.bindless_pool, NULL);
1782    }
1783 }
1784 
1785 /* entrypoint for updating bindless descriptors: called from draw/dispatch */
1786 void
zink_descriptors_update_bindless(struct zink_context * ctx)1787 zink_descriptors_update_bindless(struct zink_context *ctx)
1788 {
1789    struct zink_screen *screen = zink_screen(ctx->base.screen);
1790    VkDescriptorGetInfoEXT info;
1791    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
1792    info.pNext = NULL;
1793    /* bindless descriptors are split between images and buffers */
1794    for (unsigned i = 0; i < 2; i++) {
1795       if (!ctx->di.bindless_dirty[i])
1796          continue;
1797       while (util_dynarray_contains(&ctx->di.bindless[i].updates, uint32_t)) {
1798          /* updates are tracked by handle */
1799          uint32_t handle = util_dynarray_pop(&ctx->di.bindless[i].updates, uint32_t);
1800          bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
1801          unsigned binding = i * 2 + !!is_buffer;
1802          if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
1803             if (is_buffer) {
1804                size_t size = i ? screen->info.db_props.robustStorageTexelBufferDescriptorSize : screen->info.db_props.robustUniformTexelBufferDescriptorSize;
1805                info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
1806                info.data.pSampler = (void*)&ctx->di.bindless[i].db.buffer_infos[handle - ZINK_MAX_BINDLESS_HANDLES];
1807                VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + handle * size);
1808             } else {
1809                info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1810                if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray || i) {
1811                   size_t size = i ? screen->info.db_props.storageImageDescriptorSize : screen->info.db_props.combinedImageSamplerDescriptorSize;
1812                   info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle];
1813                   VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.bindless_db_offsets[binding] + handle * size);
1814                } else {
1815                   /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as
1816                    *
1817                    *   | array_of_samplers[] | array_of_sampled_images[] |
1818                    *
1819                    * which means each descriptor's data must be split
1820                    */
1821                   uint8_t buf[1024];
1822                   size_t size = screen->info.db_props.combinedImageSamplerDescriptorSize;
1823                   info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle];
1824                   VKSCR(GetDescriptorEXT)(screen->dev, &info, size, buf);
1825                   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);
1826                   size_t offset = screen->info.db_props.samplerDescriptorSize * ZINK_MAX_BINDLESS_HANDLES;
1827                   offset += handle * screen->info.db_props.sampledImageDescriptorSize;
1828                   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);
1829                }
1830             }
1831          } else {
1832             VkWriteDescriptorSet wd;
1833             wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1834             wd.pNext = NULL;
1835             wd.dstSet = ctx->dd.t.bindless_set;
1836             wd.dstBinding = binding;
1837             /* buffer handle ids are offset by ZINK_MAX_BINDLESS_HANDLES for internal tracking */
1838             wd.dstArrayElement = is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle;
1839             wd.descriptorCount = 1;
1840             wd.descriptorType = zink_descriptor_type_from_bindless_index(wd.dstBinding);
1841             if (is_buffer)
1842                wd.pTexelBufferView = &ctx->di.bindless[i].t.buffer_infos[wd.dstArrayElement];
1843             else
1844                wd.pImageInfo = &ctx->di.bindless[i].img_infos[handle];
1845             /* this sucks, but sets must be singly updated to be handled correctly */
1846             VKSCR(UpdateDescriptorSets)(screen->dev, 1, &wd, 0, NULL);
1847          }
1848       }
1849    }
1850    ctx->di.any_bindless_dirty = 0;
1851 }
1852