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