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