1 /*
2  * Copyright © 2021 Valve Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
25  */
26 #include "tgsi/tgsi_from_mesa.h"
27 
28 
29 
30 #include "zink_context.h"
31 #include "zink_compiler.h"
32 #include "zink_descriptors.h"
33 #include "zink_program.h"
34 #include "zink_resource.h"
35 #include "zink_screen.h"
36 
37 #define MAX_LAZY_DESCRIPTORS (ZINK_DEFAULT_MAX_DESCS / 10)
38 
39 struct zink_descriptor_data_lazy {
40    struct zink_descriptor_data base;
41    VkDescriptorUpdateTemplateEntry push_entries[PIPE_SHADER_TYPES]; //gfx+fbfetch
42    VkDescriptorUpdateTemplateEntry compute_push_entry;
43    bool push_state_changed[2]; //gfx, compute
44    uint8_t state_changed[2]; //gfx, compute
45 };
46 
47 struct zink_descriptor_pool {
48    VkDescriptorPool pool;
49    VkDescriptorSet sets[MAX_LAZY_DESCRIPTORS];
50    unsigned set_idx;
51    unsigned sets_alloc;
52 };
53 
54 struct zink_batch_descriptor_data_lazy {
55    struct zink_batch_descriptor_data base;
56    struct util_dynarray overflowed_pools;
57    struct hash_table pools[ZINK_DESCRIPTOR_TYPES];
58    struct zink_descriptor_pool *push_pool[2];
59    struct zink_program *pg[2]; //gfx, compute
60    uint32_t compat_id[2];
61    VkDescriptorSetLayout dsl[2][ZINK_DESCRIPTOR_TYPES];
62    VkDescriptorSet sets[2][ZINK_DESCRIPTOR_TYPES + 1];
63    unsigned push_usage[2];
64    bool has_fbfetch;
65 };
66 
67 ALWAYS_INLINE static struct zink_descriptor_data_lazy *
dd_lazy(struct zink_context * ctx)68 dd_lazy(struct zink_context *ctx)
69 {
70    return (struct zink_descriptor_data_lazy*)ctx->dd;
71 }
72 
73 ALWAYS_INLINE static struct zink_batch_descriptor_data_lazy *
bdd_lazy(struct zink_batch_state * bs)74 bdd_lazy(struct zink_batch_state *bs)
75 {
76    return (struct zink_batch_descriptor_data_lazy*)bs->dd;
77 }
78 
79 static void
init_template_entry(struct zink_shader * shader,enum zink_descriptor_type type,unsigned idx,unsigned offset,VkDescriptorUpdateTemplateEntry * entry,unsigned * entry_idx,bool flatten_dynamic)80 init_template_entry(struct zink_shader *shader, enum zink_descriptor_type type,
81                     unsigned idx, unsigned offset, VkDescriptorUpdateTemplateEntry *entry, unsigned *entry_idx, bool flatten_dynamic)
82 {
83     int index = shader->bindings[type][idx].index;
84     enum pipe_shader_type stage = pipe_shader_type_from_mesa(shader->nir->info.stage);
85     entry->dstArrayElement = 0;
86     entry->dstBinding = shader->bindings[type][idx].binding;
87     if (shader->bindings[type][idx].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC && flatten_dynamic)
88        /* filter out DYNAMIC type here */
89        entry->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
90     else
91        entry->descriptorType = shader->bindings[type][idx].type;
92     switch (shader->bindings[type][idx].type) {
93     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
94     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
95        entry->descriptorCount = 1;
96        entry->offset = offsetof(struct zink_context, di.ubos[stage][index + offset]);
97        entry->stride = sizeof(VkDescriptorBufferInfo);
98        break;
99     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
100        entry->descriptorCount = shader->bindings[type][idx].size;
101        entry->offset = offsetof(struct zink_context, di.textures[stage][index + offset]);
102        entry->stride = sizeof(VkDescriptorImageInfo);
103        break;
104     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
105        entry->descriptorCount = shader->bindings[type][idx].size;
106        entry->offset = offsetof(struct zink_context, di.tbos[stage][index + offset]);
107        entry->stride = sizeof(VkBufferView);
108        break;
109     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
110        entry->descriptorCount = 1;
111        entry->offset = offsetof(struct zink_context, di.ssbos[stage][index + offset]);
112        entry->stride = sizeof(VkDescriptorBufferInfo);
113        break;
114     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
115        entry->descriptorCount = shader->bindings[type][idx].size;
116        entry->offset = offsetof(struct zink_context, di.images[stage][index + offset]);
117        entry->stride = sizeof(VkDescriptorImageInfo);
118        break;
119     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
120        entry->descriptorCount = shader->bindings[type][idx].size;
121        entry->offset = offsetof(struct zink_context, di.texel_images[stage][index + offset]);
122        entry->stride = sizeof(VkBufferView);
123        break;
124     default:
125        unreachable("unknown type");
126     }
127     (*entry_idx)++;
128 }
129 
130 static uint16_t
descriptor_program_num_sizes(VkDescriptorPoolSize * sizes,enum zink_descriptor_type type)131 descriptor_program_num_sizes(VkDescriptorPoolSize *sizes, enum zink_descriptor_type type)
132 {
133    switch (type) {
134    case ZINK_DESCRIPTOR_TYPE_UBO:
135       return 1;
136    case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
137       return !!sizes[ZDS_INDEX_COMBINED_SAMPLER].descriptorCount +
138              !!sizes[ZDS_INDEX_UNIFORM_TEXELS].descriptorCount;
139    case ZINK_DESCRIPTOR_TYPE_SSBO:
140       return 1;
141    case ZINK_DESCRIPTOR_TYPE_IMAGE:
142       return !!sizes[ZDS_INDEX_STORAGE_IMAGE].descriptorCount +
143              !!sizes[ZDS_INDEX_STORAGE_TEXELS].descriptorCount;
144    default: break;
145    }
146    unreachable("unknown type");
147 }
148 
149 bool
zink_descriptor_program_init_lazy(struct zink_context * ctx,struct zink_program * pg)150 zink_descriptor_program_init_lazy(struct zink_context *ctx, struct zink_program *pg)
151 {
152    struct zink_screen *screen = zink_screen(ctx->base.screen);
153    VkDescriptorSetLayoutBinding bindings[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 32];
154    VkDescriptorUpdateTemplateEntry entries[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 32];
155    unsigned num_bindings[ZINK_DESCRIPTOR_TYPES] = {0};
156    uint8_t has_bindings = 0;
157    unsigned push_count = 0;
158    uint16_t num_type_sizes[ZINK_DESCRIPTOR_TYPES];
159    VkDescriptorPoolSize sizes[6] = {0}; //zink_descriptor_size_index
160 
161    struct zink_shader **stages;
162    if (pg->is_compute)
163       stages = &((struct zink_compute_program*)pg)->shader;
164    else
165       stages = ((struct zink_gfx_program*)pg)->shaders;
166 
167    if (!pg->dd)
168       pg->dd = (void*)rzalloc(pg, struct zink_program_descriptor_data);
169    if (!pg->dd)
170       return false;
171 
172    if (!pg->is_compute && stages[PIPE_SHADER_FRAGMENT]->nir->info.fs.uses_fbfetch_output) {
173       zink_descriptor_util_init_fbfetch(ctx);
174       push_count = 1;
175       pg->dd->fbfetch = true;
176    }
177 
178    unsigned entry_idx[ZINK_DESCRIPTOR_TYPES] = {0};
179 
180    unsigned num_shaders = pg->is_compute ? 1 : ZINK_SHADER_COUNT;
181    bool have_push = screen->info.have_KHR_push_descriptor;
182    for (int i = 0; i < num_shaders; i++) {
183       struct zink_shader *shader = stages[i];
184       if (!shader)
185          continue;
186 
187       enum pipe_shader_type stage = pipe_shader_type_from_mesa(shader->nir->info.stage);
188       VkShaderStageFlagBits stage_flags = zink_shader_stage(stage);
189       for (int j = 0; j < ZINK_DESCRIPTOR_TYPES; j++) {
190          for (int k = 0; k < shader->num_bindings[j]; k++) {
191             /* dynamic ubos handled in push */
192             if (shader->bindings[j][k].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
193                pg->dd->push_usage |= BITFIELD64_BIT(stage);
194 
195                push_count++;
196                continue;
197             }
198 
199             assert(num_bindings[j] < ARRAY_SIZE(bindings[j]));
200             VkDescriptorSetLayoutBinding *binding = &bindings[j][num_bindings[j]];
201             binding->binding = shader->bindings[j][k].binding;
202             binding->descriptorType = shader->bindings[j][k].type;
203             binding->descriptorCount = shader->bindings[j][k].size;
204             binding->stageFlags = stage_flags;
205             binding->pImmutableSamplers = NULL;
206 
207             enum zink_descriptor_size_index idx = zink_vktype_to_size_idx(shader->bindings[j][k].type);
208             sizes[idx].descriptorCount += shader->bindings[j][k].size;
209             sizes[idx].type = shader->bindings[j][k].type;
210             switch (shader->bindings[j][k].type) {
211             case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
212             case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
213             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
214             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
215                init_template_entry(shader, j, k, 0, &entries[j][entry_idx[j]], &entry_idx[j], screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY);
216                break;
217             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
218             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
219                for (unsigned l = 0; l < shader->bindings[j][k].size; l++)
220                   init_template_entry(shader, j, k, l, &entries[j][entry_idx[j]], &entry_idx[j], screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY);
221                break;
222             default:
223                break;
224             }
225             num_bindings[j]++;
226             has_bindings |= BITFIELD_BIT(j);
227          }
228          num_type_sizes[j] = descriptor_program_num_sizes(sizes, j);
229       }
230       pg->dd->bindless |= shader->bindless;
231    }
232    if (pg->dd->bindless)
233       zink_descriptors_init_bindless(ctx);
234    pg->dd->binding_usage = has_bindings;
235    if (!has_bindings && !push_count) {
236       ralloc_free(pg->dd);
237       pg->dd = NULL;
238 
239       pg->layout = zink_pipeline_layout_create(screen, pg, &pg->compat_id);
240       return !!pg->layout;
241    }
242 
243    pg->dsl[pg->num_dsl++] = push_count ? ctx->dd->push_dsl[pg->is_compute]->layout : ctx->dd->dummy_dsl->layout;
244    if (has_bindings) {
245       for (unsigned i = 0; i < ARRAY_SIZE(sizes); i++)
246          sizes[i].descriptorCount *= screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY ? MAX_LAZY_DESCRIPTORS : ZINK_DEFAULT_MAX_DESCS;
247       u_foreach_bit(type, has_bindings) {
248          for (unsigned i = 0; i < type; i++) {
249             /* push set is always 0 */
250             if (!pg->dsl[i + 1]) {
251                /* inject a null dsl */
252                pg->dsl[pg->num_dsl++] = ctx->dd->dummy_dsl->layout;
253                pg->dd->binding_usage |= BITFIELD_BIT(i);
254             }
255          }
256          struct zink_descriptor_layout_key *key;
257          pg->dd->layouts[pg->num_dsl] = zink_descriptor_util_layout_get(ctx, type, bindings[type], num_bindings[type], &key);
258          enum zink_descriptor_size_index idx = zink_descriptor_type_to_size_idx(type);
259          VkDescriptorPoolSize *sz = &sizes[idx];
260          if (!sz->descriptorCount)
261             sz++;
262          pg->dd->pool_key[type] = zink_descriptor_util_pool_key_get(ctx, type, key, sz, num_type_sizes[type]);
263          pg->dd->pool_key[type]->use_count++;
264          pg->dsl[pg->num_dsl] = pg->dd->layouts[pg->num_dsl]->layout;
265          pg->num_dsl++;
266       }
267    }
268    /* TODO: make this dynamic? */
269    if (pg->dd->bindless) {
270       pg->num_dsl = ZINK_DESCRIPTOR_BINDLESS + 1;
271       pg->dsl[ZINK_DESCRIPTOR_BINDLESS] = ctx->dd->bindless_layout;
272       for (unsigned i = 0; i < ZINK_DESCRIPTOR_BINDLESS; i++) {
273          if (!pg->dsl[i]) {
274             /* inject a null dsl */
275             pg->dsl[i] = ctx->dd->dummy_dsl->layout;
276             if (i != ZINK_DESCRIPTOR_TYPES)
277                pg->dd->binding_usage |= BITFIELD_BIT(i);
278          }
279       }
280    }
281 
282    pg->layout = zink_pipeline_layout_create(screen, pg, &pg->compat_id);
283    if (!pg->layout)
284       return false;
285    if (!screen->info.have_KHR_descriptor_update_template || screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_NOTEMPLATES)
286       return true;
287 
288    VkDescriptorUpdateTemplateCreateInfo template[ZINK_DESCRIPTOR_TYPES + 1] = {0};
289    /* type of template */
290    VkDescriptorUpdateTemplateType types[ZINK_DESCRIPTOR_TYPES + 1] = {VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET};
291    if (have_push && screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY)
292       types[0] = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
293 
294    /* number of descriptors in template */
295    unsigned wd_count[ZINK_DESCRIPTOR_TYPES + 1];
296    if (push_count)
297       wd_count[0] = pg->is_compute ? 1 : (ZINK_SHADER_COUNT + !!ctx->dd->has_fbfetch);
298    for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
299       wd_count[i + 1] = pg->dd->pool_key[i] ? pg->dd->pool_key[i]->layout->num_bindings : 0;
300 
301    VkDescriptorUpdateTemplateEntry *push_entries[2] = {
302       dd_lazy(ctx)->push_entries,
303       &dd_lazy(ctx)->compute_push_entry,
304    };
305    for (unsigned i = 0; i < pg->num_dsl; i++) {
306       bool is_push = i == 0;
307       /* no need for empty templates */
308       if (pg->dsl[i] == ctx->dd->dummy_dsl->layout ||
309           pg->dsl[i] == ctx->dd->bindless_layout ||
310           (!is_push && pg->dd->layouts[i]->desc_template))
311          continue;
312       template[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
313       assert(wd_count[i]);
314       template[i].descriptorUpdateEntryCount = wd_count[i];
315       if (is_push)
316          template[i].pDescriptorUpdateEntries = push_entries[pg->is_compute];
317       else
318          template[i].pDescriptorUpdateEntries = entries[i - 1];
319       template[i].templateType = types[i];
320       template[i].descriptorSetLayout = pg->dsl[i];
321       template[i].pipelineBindPoint = pg->is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
322       template[i].pipelineLayout = pg->layout;
323       template[i].set = i;
324       VkDescriptorUpdateTemplateKHR t;
325       if (VKSCR(CreateDescriptorUpdateTemplate)(screen->dev, &template[i], NULL, &t) != VK_SUCCESS)
326          return false;
327       if (is_push)
328          pg->dd->push_template = t;
329       else
330          pg->dd->layouts[i]->desc_template = t;
331    }
332    return true;
333 }
334 
335 void
zink_descriptor_program_deinit_lazy(struct zink_context * ctx,struct zink_program * pg)336 zink_descriptor_program_deinit_lazy(struct zink_context *ctx, struct zink_program *pg)
337 {
338    struct zink_screen *screen = zink_screen(ctx->base.screen);
339    for (unsigned i = 0; pg->num_dsl && i < ZINK_DESCRIPTOR_TYPES; i++) {
340       if (pg->dd->pool_key[i])
341          pg->dd->pool_key[i]->use_count--;
342    }
343    if (pg->dd && pg->dd->push_template)
344       VKSCR(DestroyDescriptorUpdateTemplate)(screen->dev, pg->dd->push_template, NULL);
345    ralloc_free(pg->dd);
346 }
347 
348 static VkDescriptorPool
create_pool(struct zink_screen * screen,unsigned num_type_sizes,const VkDescriptorPoolSize * sizes,unsigned flags)349 create_pool(struct zink_screen *screen, unsigned num_type_sizes, const VkDescriptorPoolSize *sizes, unsigned flags)
350 {
351    VkDescriptorPool pool;
352    VkDescriptorPoolCreateInfo dpci = {0};
353    dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
354    dpci.pPoolSizes = sizes;
355    dpci.poolSizeCount = num_type_sizes;
356    dpci.flags = flags;
357    dpci.maxSets = MAX_LAZY_DESCRIPTORS;
358    if (VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &pool) != VK_SUCCESS) {
359       mesa_loge("ZINK: vkCreateDescriptorPool failed");
360       return VK_NULL_HANDLE;
361    }
362    return pool;
363 }
364 
365 static struct zink_descriptor_pool *
366 get_descriptor_pool_lazy(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_descriptor_data_lazy *bdd, bool is_compute);
367 
368 static struct zink_descriptor_pool *
check_pool_alloc(struct zink_context * ctx,struct zink_descriptor_pool * pool,struct hash_entry * he,struct zink_program * pg,enum zink_descriptor_type type,struct zink_batch_descriptor_data_lazy * bdd,bool is_compute)369 check_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool *pool, struct hash_entry *he, struct zink_program *pg,
370                  enum zink_descriptor_type type, struct zink_batch_descriptor_data_lazy *bdd, bool is_compute)
371 {
372    struct zink_screen *screen = zink_screen(ctx->base.screen);
373    /* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
374    if (pool->set_idx == pool->sets_alloc) {
375       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
376       if (!sets_to_alloc) {
377          /* overflowed pool: queue for deletion on next reset */
378          util_dynarray_append(&bdd->overflowed_pools, struct zink_descriptor_pool*, pool);
379          _mesa_hash_table_remove(&bdd->pools[type], he);
380          return get_descriptor_pool_lazy(ctx, pg, type, bdd, is_compute);
381       }
382       if (!zink_descriptor_util_alloc_sets(screen, pg->dsl[type + 1],
383                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc))
384          return NULL;
385       pool->sets_alloc += sets_to_alloc;
386    }
387    return pool;
388 }
389 
390 static struct zink_descriptor_pool *
create_push_pool(struct zink_screen * screen,struct zink_batch_descriptor_data_lazy * bdd,bool is_compute,bool has_fbfetch)391 create_push_pool(struct zink_screen *screen, struct zink_batch_descriptor_data_lazy *bdd, bool is_compute, bool has_fbfetch)
392 {
393    struct zink_descriptor_pool *pool = rzalloc(bdd, struct zink_descriptor_pool);
394    VkDescriptorPoolSize sizes[2];
395    sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
396    if (is_compute)
397       sizes[0].descriptorCount = MAX_LAZY_DESCRIPTORS;
398    else {
399       sizes[0].descriptorCount = ZINK_SHADER_COUNT * MAX_LAZY_DESCRIPTORS;
400       sizes[1].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
401       sizes[1].descriptorCount = MAX_LAZY_DESCRIPTORS;
402    }
403    pool->pool = create_pool(screen, !is_compute && has_fbfetch ? 2 : 1, sizes, 0);
404    return pool;
405 }
406 
407 static struct zink_descriptor_pool *
check_push_pool_alloc(struct zink_context * ctx,struct zink_descriptor_pool * pool,struct zink_batch_descriptor_data_lazy * bdd,bool is_compute)408 check_push_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool *pool, struct zink_batch_descriptor_data_lazy *bdd, bool is_compute)
409 {
410    struct zink_screen *screen = zink_screen(ctx->base.screen);
411    /* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
412    if (pool->set_idx == pool->sets_alloc || unlikely(ctx->dd->has_fbfetch != bdd->has_fbfetch)) {
413       unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
414       if (!sets_to_alloc || unlikely(ctx->dd->has_fbfetch != bdd->has_fbfetch)) {
415          /* overflowed pool: queue for deletion on next reset */
416          util_dynarray_append(&bdd->overflowed_pools, struct zink_descriptor_pool*, pool);
417          bdd->push_pool[is_compute] = create_push_pool(screen, bdd, is_compute, ctx->dd->has_fbfetch);
418          bdd->has_fbfetch = ctx->dd->has_fbfetch;
419          return check_push_pool_alloc(ctx, bdd->push_pool[is_compute], bdd, is_compute);
420       }
421       if (!zink_descriptor_util_alloc_sets(screen, ctx->dd->push_dsl[is_compute]->layout,
422                                            pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc))
423          return NULL;
424       pool->sets_alloc += sets_to_alloc;
425    }
426    return pool;
427 }
428 
429 static struct zink_descriptor_pool *
get_descriptor_pool_lazy(struct zink_context * ctx,struct zink_program * pg,enum zink_descriptor_type type,struct zink_batch_descriptor_data_lazy * bdd,bool is_compute)430 get_descriptor_pool_lazy(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_descriptor_data_lazy *bdd, bool is_compute)
431 {
432    struct zink_screen *screen = zink_screen(ctx->base.screen);
433    const struct zink_descriptor_pool_key *pool_key = pg->dd->pool_key[type];
434    struct hash_entry *he = _mesa_hash_table_search(&bdd->pools[type], pool_key);
435    struct zink_descriptor_pool *pool;
436    if (he) {
437       pool = he->data;
438       return check_pool_alloc(ctx, pool, he, pg, type, bdd, is_compute);
439    }
440    pool = rzalloc(bdd, struct zink_descriptor_pool);
441    if (!pool)
442       return NULL;
443    const unsigned num_type_sizes = pool_key->sizes[1].descriptorCount ? 2 : 1;
444    pool->pool = create_pool(screen, num_type_sizes, pool_key->sizes, 0);
445    if (!pool->pool) {
446       ralloc_free(pool);
447       return NULL;
448    }
449    _mesa_hash_table_insert(&bdd->pools[type], pool_key, pool);
450    return check_pool_alloc(ctx, pool, he, pg, type, bdd, is_compute);
451 }
452 
453 ALWAYS_INLINE static VkDescriptorSet
get_descriptor_set_lazy(struct zink_descriptor_pool * pool)454 get_descriptor_set_lazy(struct zink_descriptor_pool *pool)
455 {
456    if (!pool)
457       return VK_NULL_HANDLE;
458 
459    assert(pool->set_idx < pool->sets_alloc);
460    return pool->sets[pool->set_idx++];
461 }
462 
463 static bool
populate_sets(struct zink_context * ctx,struct zink_batch_descriptor_data_lazy * bdd,struct zink_program * pg,uint8_t * changed_sets,VkDescriptorSet * sets)464 populate_sets(struct zink_context *ctx, struct zink_batch_descriptor_data_lazy *bdd,
465               struct zink_program *pg, uint8_t *changed_sets, VkDescriptorSet *sets)
466 {
467    u_foreach_bit(type, *changed_sets) {
468       if (pg->dd->pool_key[type]) {
469          struct zink_descriptor_pool *pool = get_descriptor_pool_lazy(ctx, pg, type, bdd, pg->is_compute);
470          sets[type] = get_descriptor_set_lazy(pool);
471          if (!sets[type])
472             return false;
473       } else
474          sets[type] = VK_NULL_HANDLE;
475    }
476    return true;
477 }
478 
479 void
zink_descriptor_set_update_lazy(struct zink_context * ctx,struct zink_program * pg,enum zink_descriptor_type type,VkDescriptorSet set)480 zink_descriptor_set_update_lazy(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, VkDescriptorSet set)
481 {
482    struct zink_screen *screen = zink_screen(ctx->base.screen);
483    VKCTX(UpdateDescriptorSetWithTemplate)(screen->dev, set, pg->dd->layouts[type + 1]->desc_template, ctx);
484 }
485 
486 void
zink_descriptors_update_lazy_masked(struct zink_context * ctx,bool is_compute,uint8_t changed_sets,uint8_t bind_sets)487 zink_descriptors_update_lazy_masked(struct zink_context *ctx, bool is_compute, uint8_t changed_sets, uint8_t bind_sets)
488 {
489    struct zink_screen *screen = zink_screen(ctx->base.screen);
490    struct zink_batch_state *bs = ctx->batch.state;
491    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
492    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
493    VkDescriptorSet desc_sets[ZINK_DESCRIPTOR_TYPES];
494    if (!pg->dd->binding_usage || (!changed_sets && !bind_sets))
495       return;
496 
497    if (!populate_sets(ctx, bdd, pg, &changed_sets, desc_sets)) {
498       debug_printf("ZINK: couldn't get descriptor sets!\n");
499       return;
500    }
501    /* no flushing allowed */
502    assert(ctx->batch.state == bs);
503 
504    u_foreach_bit(type, changed_sets) {
505       assert(type + 1 < pg->num_dsl);
506       if (pg->dd->pool_key[type]) {
507          VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[type], pg->dd->layouts[type + 1]->desc_template, ctx);
508          VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
509                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
510                                  /* set index incremented by 1 to account for push set */
511                                  pg->layout, type + 1, 1, &desc_sets[type],
512                                  0, NULL);
513          bdd->sets[is_compute][type + 1] = desc_sets[type];
514       }
515    }
516    u_foreach_bit(type, bind_sets & ~changed_sets) {
517       if (!pg->dd->pool_key[type])
518          continue;
519       assert(bdd->sets[is_compute][type + 1]);
520       VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
521                               is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
522                               /* set index incremented by 1 to account for push set */
523                               pg->layout, type + 1, 1, &bdd->sets[is_compute][type + 1],
524                               0, NULL);
525    }
526 }
527 
528 /* only called by cached manager for fbfetch handling */
529 VkDescriptorSet
zink_descriptors_alloc_lazy_push(struct zink_context * ctx)530 zink_descriptors_alloc_lazy_push(struct zink_context *ctx)
531 {
532    struct zink_batch_state *bs = ctx->batch.state;
533    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
534    struct zink_screen *screen = zink_screen(ctx->base.screen);
535    VkDescriptorSet push_set = VK_NULL_HANDLE;
536    if (!bdd->push_pool[0]) {
537       bdd->push_pool[0] = create_push_pool(screen, bdd, false, true);
538       bdd->has_fbfetch = true;
539    }
540    struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, bdd->push_pool[0], bdd, false);
541    push_set = get_descriptor_set_lazy(pool);
542    if (!push_set)
543       mesa_loge("ZINK: failed to get push descriptor set!");
544    return push_set;
545 }
546 
547 void
zink_descriptors_update_lazy(struct zink_context * ctx,bool is_compute)548 zink_descriptors_update_lazy(struct zink_context *ctx, bool is_compute)
549 {
550    struct zink_batch_state *bs = ctx->batch.state;
551    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
552    struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
553    struct zink_screen *screen = zink_screen(ctx->base.screen);
554    bool have_KHR_push_descriptor = screen->info.have_KHR_push_descriptor;
555 
556    bool batch_changed = !bdd->pg[is_compute];
557    if (batch_changed) {
558       /* update all sets and bind null sets */
559       dd_lazy(ctx)->state_changed[is_compute] = pg->dd->binding_usage;
560       dd_lazy(ctx)->push_state_changed[is_compute] = !!pg->dd->push_usage;
561    }
562 
563    if (pg != bdd->pg[is_compute]) {
564       /* if we don't already know that we have to update all sets,
565        * check to see if any dsls changed
566        *
567        * also always update the dsl pointers on program change
568        */
569        for (unsigned i = 0; i < ARRAY_SIZE(bdd->dsl[is_compute]); i++) {
570           /* push set is already detected, start at 1 */
571           if (bdd->dsl[is_compute][i] != pg->dsl[i + 1])
572              dd_lazy(ctx)->state_changed[is_compute] |= BITFIELD_BIT(i);
573           bdd->dsl[is_compute][i] = pg->dsl[i + 1];
574        }
575        dd_lazy(ctx)->push_state_changed[is_compute] |= bdd->push_usage[is_compute] != pg->dd->push_usage;
576        bdd->push_usage[is_compute] = pg->dd->push_usage;
577    }
578 
579    uint8_t changed_sets = pg->dd->binding_usage & dd_lazy(ctx)->state_changed[is_compute];
580    bool need_push = pg->dd->push_usage &&
581                     (dd_lazy(ctx)->push_state_changed[is_compute] || batch_changed);
582    VkDescriptorSet push_set = VK_NULL_HANDLE;
583    if (need_push && !have_KHR_push_descriptor) {
584       struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, bdd->push_pool[pg->is_compute], bdd, pg->is_compute);
585       push_set = get_descriptor_set_lazy(pool);
586       if (!push_set) {
587          mesa_loge("ZINK: failed to get push descriptor set!");
588          /* just jam something in to avoid a hang */
589          push_set = ctx->dd->dummy_set;
590       }
591    }
592    /*
593     * when binding a pipeline, the pipeline can correctly access any previously bound
594     * descriptor sets which were bound with compatible pipeline layouts
595     * VK 14.2.2
596     */
597    uint8_t bind_sets = bdd->pg[is_compute] && bdd->compat_id[is_compute] == pg->compat_id ? 0 : pg->dd->binding_usage;
598    if (pg->dd->push_usage && (dd_lazy(ctx)->push_state_changed[is_compute] || bind_sets)) {
599       if (have_KHR_push_descriptor) {
600          if (dd_lazy(ctx)->push_state_changed[is_compute])
601             VKCTX(CmdPushDescriptorSetWithTemplateKHR)(bs->cmdbuf, pg->dd->push_template,
602                                                         pg->layout, 0, ctx);
603       } else {
604          if (dd_lazy(ctx)->push_state_changed[is_compute]) {
605             VKCTX(UpdateDescriptorSetWithTemplate)(screen->dev, push_set, pg->dd->push_template, ctx);
606             bdd->sets[is_compute][0] = push_set;
607          }
608          assert(push_set || bdd->sets[is_compute][0]);
609          VKCTX(CmdBindDescriptorSets)(bs->cmdbuf,
610                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
611                                  pg->layout, 0, 1, push_set ? &push_set : &bdd->sets[is_compute][0],
612                                  0, NULL);
613       }
614    }
615    dd_lazy(ctx)->push_state_changed[is_compute] = false;
616    zink_descriptors_update_lazy_masked(ctx, is_compute, changed_sets, bind_sets);
617    if (pg->dd->bindless && unlikely(!ctx->dd->bindless_bound)) {
618       VKCTX(CmdBindDescriptorSets)(ctx->batch.state->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
619                                    pg->layout, ZINK_DESCRIPTOR_BINDLESS, 1, &ctx->dd->bindless_set,
620                                    0, NULL);
621       ctx->dd->bindless_bound = true;
622    }
623    bdd->pg[is_compute] = pg;
624    ctx->dd->pg[is_compute] = pg;
625    bdd->compat_id[is_compute] = pg->compat_id;
626    dd_lazy(ctx)->state_changed[is_compute] = false;
627 }
628 
629 void
zink_context_invalidate_descriptor_state_lazy(struct zink_context * ctx,enum pipe_shader_type shader,enum zink_descriptor_type type,unsigned start,unsigned count)630 zink_context_invalidate_descriptor_state_lazy(struct zink_context *ctx, enum pipe_shader_type shader, enum zink_descriptor_type type, unsigned start, unsigned count)
631 {
632    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
633       dd_lazy(ctx)->push_state_changed[shader == PIPE_SHADER_COMPUTE] = true;
634    else
635       dd_lazy(ctx)->state_changed[shader == PIPE_SHADER_COMPUTE] |= BITFIELD_BIT(type);
636 }
637 
638 void
zink_batch_descriptor_deinit_lazy(struct zink_screen * screen,struct zink_batch_state * bs)639 zink_batch_descriptor_deinit_lazy(struct zink_screen *screen, struct zink_batch_state *bs)
640 {
641    if (!bs->dd)
642       return;
643    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
644    if (screen->info.have_KHR_descriptor_update_template) {
645       for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
646          hash_table_foreach(&bdd->pools[i], entry) {
647             struct zink_descriptor_pool *pool = (void*)entry->data;
648             VKSCR(DestroyDescriptorPool)(screen->dev, pool->pool, NULL);
649          }
650       }
651       if (bdd->push_pool[0])
652          VKSCR(DestroyDescriptorPool)(screen->dev, bdd->push_pool[0]->pool, NULL);
653       if (bdd->push_pool[1])
654          VKSCR(DestroyDescriptorPool)(screen->dev, bdd->push_pool[1]->pool, NULL);
655    }
656    ralloc_free(bs->dd);
657 }
658 
659 static void
pool_destroy(struct zink_screen * screen,struct zink_descriptor_pool * pool)660 pool_destroy(struct zink_screen *screen, struct zink_descriptor_pool *pool)
661 {
662    VKSCR(DestroyDescriptorPool)(screen->dev, pool->pool, NULL);
663    ralloc_free(pool);
664 }
665 
666 void
zink_batch_descriptor_reset_lazy(struct zink_screen * screen,struct zink_batch_state * bs)667 zink_batch_descriptor_reset_lazy(struct zink_screen *screen, struct zink_batch_state *bs)
668 {
669    if (!screen->info.have_KHR_descriptor_update_template)
670       return;
671    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
672    for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
673       hash_table_foreach(&bdd->pools[i], entry) {
674          const struct zink_descriptor_pool_key *key = entry->key;
675          struct zink_descriptor_pool *pool = (void*)entry->data;
676          if (key->use_count)
677             pool->set_idx = 0;
678          else {
679             pool_destroy(screen, pool);
680             _mesa_hash_table_remove(&bdd->pools[i], entry);
681          }
682       }
683    }
684    for (unsigned i = 0; i < 2; i++) {
685       bdd->pg[i] = NULL;
686       if (bdd->push_pool[i])
687          bdd->push_pool[i]->set_idx = 0;
688    }
689    while (util_dynarray_num_elements(&bdd->overflowed_pools, struct zink_descriptor_pool*)) {
690       struct zink_descriptor_pool *pool = util_dynarray_pop(&bdd->overflowed_pools, struct zink_descriptor_pool*);
691       pool_destroy(screen, pool);
692    }
693 }
694 
695 bool
zink_batch_descriptor_init_lazy(struct zink_screen * screen,struct zink_batch_state * bs)696 zink_batch_descriptor_init_lazy(struct zink_screen *screen, struct zink_batch_state *bs)
697 {
698    bs->dd = (void*)rzalloc(bs, struct zink_batch_descriptor_data_lazy);
699    if (!bs->dd)
700       return false;
701    if (!screen->info.have_KHR_descriptor_update_template)
702       return true;
703    struct zink_batch_descriptor_data_lazy *bdd = bdd_lazy(bs);
704    for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
705       if (!_mesa_hash_table_init(&bdd->pools[i], bs->dd, _mesa_hash_pointer, _mesa_key_pointer_equal))
706          return false;
707    }
708    util_dynarray_init(&bdd->overflowed_pools, bs->dd);
709    if (!screen->info.have_KHR_push_descriptor) {
710       bdd->push_pool[0] = create_push_pool(screen, bdd, false, false);
711       bdd->push_pool[1] = create_push_pool(screen, bdd, true, false);
712    }
713    return true;
714 }
715 
716 static void
init_push_template_entry(VkDescriptorUpdateTemplateEntry * entry,unsigned i)717 init_push_template_entry(VkDescriptorUpdateTemplateEntry *entry, unsigned i)
718 {
719    entry->dstBinding = tgsi_processor_to_shader_stage(i);
720    entry->descriptorCount = 1;
721    entry->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
722    entry->offset = offsetof(struct zink_context, di.ubos[i][0]);
723    entry->stride = sizeof(VkDescriptorBufferInfo);
724 }
725 
726 bool
zink_descriptors_init_lazy(struct zink_context * ctx)727 zink_descriptors_init_lazy(struct zink_context *ctx)
728 {
729    struct zink_screen *screen = zink_screen(ctx->base.screen);
730    ctx->dd = (void*)rzalloc(ctx, struct zink_descriptor_data_lazy);
731    if (!ctx->dd)
732       return false;
733 
734    if (screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_NOTEMPLATES)
735       printf("ZINK: CACHED/NOTEMPLATES DESCRIPTORS\n");
736    else if (screen->info.have_KHR_descriptor_update_template) {
737       for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
738          VkDescriptorUpdateTemplateEntry *entry = &dd_lazy(ctx)->push_entries[i];
739          init_push_template_entry(entry, i);
740       }
741       init_push_template_entry(&dd_lazy(ctx)->compute_push_entry, PIPE_SHADER_COMPUTE);
742       VkDescriptorUpdateTemplateEntry *entry = &dd_lazy(ctx)->push_entries[ZINK_SHADER_COUNT]; //fbfetch
743       entry->dstBinding = ZINK_FBFETCH_BINDING;
744       entry->descriptorCount = 1;
745       entry->descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
746       entry->offset = offsetof(struct zink_context, di.fbfetch);
747       entry->stride = sizeof(VkDescriptorImageInfo);
748       if (screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY)
749          printf("ZINK: USING LAZY DESCRIPTORS\n");
750    }
751    struct zink_descriptor_layout_key *layout_key;
752    if (!zink_descriptor_util_push_layouts_get(ctx, ctx->dd->push_dsl, ctx->dd->push_layout_keys))
753       return false;
754 
755    ctx->dd->dummy_dsl = zink_descriptor_util_layout_get(ctx, 0, NULL, 0, &layout_key);
756    if (!ctx->dd->dummy_dsl)
757       return false;
758 
759    return true;
760 }
761 
762 void
zink_descriptors_deinit_lazy(struct zink_context * ctx)763 zink_descriptors_deinit_lazy(struct zink_context *ctx)
764 {
765    if (ctx->dd) {
766       struct zink_screen *screen = zink_screen(ctx->base.screen);
767       if (ctx->dd->dummy_pool)
768          VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd->dummy_pool, NULL);
769       if (ctx->dd->push_dsl[0])
770          VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd->push_dsl[0]->layout, NULL);
771       if (ctx->dd->push_dsl[1])
772          VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd->push_dsl[1]->layout, NULL);
773    }
774    ralloc_free(ctx->dd);
775 }
776