1 /*
2 * Copyright © 2019 Raspberry Pi Ltd
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "vk_descriptors.h"
25 #include "vk_util.h"
26
27 #include "v3dv_private.h"
28
29 /*
30 * For a given descriptor defined by the descriptor_set it belongs, its
31 * binding layout, and array_index, it returns the map region assigned to it
32 * from the descriptor pool bo.
33 */
34 static void *
descriptor_bo_map(struct v3dv_device * device,struct v3dv_descriptor_set * set,const struct v3dv_descriptor_set_binding_layout * binding_layout,uint32_t array_index)35 descriptor_bo_map(struct v3dv_device *device,
36 struct v3dv_descriptor_set *set,
37 const struct v3dv_descriptor_set_binding_layout *binding_layout,
38 uint32_t array_index)
39 {
40 /* Inline uniform blocks use BO memory to store UBO contents, not
41 * descriptor data, so their descriptor BO size is 0 even though they
42 * do use BO memory.
43 */
44 uint32_t bo_size = v3dv_X(device, descriptor_bo_size)(binding_layout->type);
45 assert(bo_size > 0 ||
46 binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK);
47
48 return set->pool->bo->map +
49 set->base_offset + binding_layout->descriptor_offset +
50 array_index * bo_size;
51 }
52
53 static bool
descriptor_type_is_dynamic(VkDescriptorType type)54 descriptor_type_is_dynamic(VkDescriptorType type)
55 {
56 switch (type) {
57 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
58 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
59 return true;
60 break;
61 default:
62 return false;
63 }
64 }
65
66 /*
67 * Tries to get a real descriptor using a descriptor map index from the
68 * descriptor_state + pipeline_layout.
69 */
70 struct v3dv_descriptor *
v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index,uint32_t * dynamic_offset)71 v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,
72 struct v3dv_descriptor_map *map,
73 struct v3dv_pipeline_layout *pipeline_layout,
74 uint32_t index,
75 uint32_t *dynamic_offset)
76 {
77 assert(index < map->num_desc);
78
79 uint32_t set_number = map->set[index];
80 assert((descriptor_state->valid & 1 << set_number));
81
82 struct v3dv_descriptor_set *set =
83 descriptor_state->descriptor_sets[set_number];
84 assert(set);
85
86 uint32_t binding_number = map->binding[index];
87 assert(binding_number < set->layout->binding_count);
88
89 const struct v3dv_descriptor_set_binding_layout *binding_layout =
90 &set->layout->binding[binding_number];
91
92 uint32_t array_index = map->array_index[index];
93 assert(array_index < binding_layout->array_size);
94
95 if (descriptor_type_is_dynamic(binding_layout->type)) {
96 uint32_t dynamic_offset_index =
97 pipeline_layout->set[set_number].dynamic_offset_start +
98 binding_layout->dynamic_offset_index + array_index;
99
100 *dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];
101 }
102
103 return &set->descriptors[binding_layout->descriptor_index + array_index];
104 }
105
106 /* Equivalent to map_get_descriptor but it returns a reloc with the bo
107 * associated with that descriptor (suballocation of the descriptor pool bo)
108 *
109 * It also returns the descriptor type, so the caller could do extra
110 * validation or adding extra offsets if the bo contains more that one field.
111 */
112 struct v3dv_cl_reloc
v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device * device,struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index,VkDescriptorType * out_type)113 v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device,
114 struct v3dv_descriptor_state *descriptor_state,
115 struct v3dv_descriptor_map *map,
116 struct v3dv_pipeline_layout *pipeline_layout,
117 uint32_t index,
118 VkDescriptorType *out_type)
119 {
120 assert(index < map->num_desc);
121
122 uint32_t set_number = map->set[index];
123 assert(descriptor_state->valid & 1 << set_number);
124
125 struct v3dv_descriptor_set *set =
126 descriptor_state->descriptor_sets[set_number];
127 assert(set);
128
129 uint32_t binding_number = map->binding[index];
130 assert(binding_number < set->layout->binding_count);
131
132 const struct v3dv_descriptor_set_binding_layout *binding_layout =
133 &set->layout->binding[binding_number];
134
135 assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK ||
136 v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);
137 if (out_type)
138 *out_type = binding_layout->type;
139
140 uint32_t array_index = map->array_index[index];
141 assert(array_index < binding_layout->array_size);
142
143 struct v3dv_cl_reloc reloc = {
144 .bo = set->pool->bo,
145 .offset = set->base_offset + binding_layout->descriptor_offset +
146 array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type),
147 };
148
149 return reloc;
150 }
151
152 /*
153 * The difference between this method and v3dv_descriptor_map_get_descriptor,
154 * is that if the sampler are added as immutable when creating the set layout,
155 * they are bound to the set layout, so not part of the descriptor per
156 * se. This method return early in that case.
157 */
158 const struct v3dv_sampler *
v3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index)159 v3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state *descriptor_state,
160 struct v3dv_descriptor_map *map,
161 struct v3dv_pipeline_layout *pipeline_layout,
162 uint32_t index)
163 {
164 assert(index < map->num_desc);
165
166 uint32_t set_number = map->set[index];
167 assert(descriptor_state->valid & 1 << set_number);
168
169 struct v3dv_descriptor_set *set =
170 descriptor_state->descriptor_sets[set_number];
171 assert(set);
172
173 uint32_t binding_number = map->binding[index];
174 assert(binding_number < set->layout->binding_count);
175
176 const struct v3dv_descriptor_set_binding_layout *binding_layout =
177 &set->layout->binding[binding_number];
178
179 uint32_t array_index = map->array_index[index];
180 assert(array_index < binding_layout->array_size);
181
182 if (binding_layout->immutable_samplers_offset != 0) {
183 assert(binding_layout->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
184 binding_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
185
186 const struct v3dv_sampler *immutable_samplers =
187 v3dv_immutable_samplers(set->layout, binding_layout);
188
189 assert(immutable_samplers);
190 const struct v3dv_sampler *sampler = &immutable_samplers[array_index];
191 assert(sampler);
192
193 return sampler;
194 }
195
196 struct v3dv_descriptor *descriptor =
197 &set->descriptors[binding_layout->descriptor_index + array_index];
198
199 assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
200 descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
201
202 assert(descriptor->sampler);
203
204 return descriptor->sampler;
205 }
206
207
208 struct v3dv_cl_reloc
v3dv_descriptor_map_get_sampler_state(struct v3dv_device * device,struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index)209 v3dv_descriptor_map_get_sampler_state(struct v3dv_device *device,
210 struct v3dv_descriptor_state *descriptor_state,
211 struct v3dv_descriptor_map *map,
212 struct v3dv_pipeline_layout *pipeline_layout,
213 uint32_t index)
214 {
215 VkDescriptorType type;
216 struct v3dv_cl_reloc reloc =
217 v3dv_descriptor_map_get_descriptor_bo(device, descriptor_state, map,
218 pipeline_layout,
219 index, &type);
220
221 assert(type == VK_DESCRIPTOR_TYPE_SAMPLER ||
222 type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
223
224 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
225 reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
226
227 return reloc;
228 }
229
230 struct v3dv_bo*
v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index)231 v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,
232 struct v3dv_descriptor_map *map,
233 struct v3dv_pipeline_layout *pipeline_layout,
234 uint32_t index)
235
236 {
237 struct v3dv_descriptor *descriptor =
238 v3dv_descriptor_map_get_descriptor(descriptor_state, map,
239 pipeline_layout, index, NULL);
240
241 switch (descriptor->type) {
242 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
243 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
244 assert(descriptor->buffer_view);
245 return descriptor->buffer_view->buffer->mem->bo;
246 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
247 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
248 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
249 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
250 assert(descriptor->image_view);
251 struct v3dv_image *image =
252 (struct v3dv_image *) descriptor->image_view->vk.image;
253 return image->mem->bo;
254 }
255 default:
256 unreachable("descriptor type doesn't has a texture bo");
257 }
258 }
259
260 struct v3dv_cl_reloc
v3dv_descriptor_map_get_texture_shader_state(struct v3dv_device * device,struct v3dv_descriptor_state * descriptor_state,struct v3dv_descriptor_map * map,struct v3dv_pipeline_layout * pipeline_layout,uint32_t index)261 v3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device,
262 struct v3dv_descriptor_state *descriptor_state,
263 struct v3dv_descriptor_map *map,
264 struct v3dv_pipeline_layout *pipeline_layout,
265 uint32_t index)
266 {
267 VkDescriptorType type;
268 struct v3dv_cl_reloc reloc =
269 v3dv_descriptor_map_get_descriptor_bo(device,
270 descriptor_state, map,
271 pipeline_layout,
272 index, &type);
273
274 assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
275 type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
276 type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
277 type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
278 type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
279 type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
280
281 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
282 reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)();
283
284 return reloc;
285 }
286
287 #define SHA1_UPDATE_VALUE(ctx, x) _mesa_sha1_update(ctx, &(x), sizeof(x));
288
289 static void
sha1_update_descriptor_set_binding_layout(struct mesa_sha1 * ctx,const struct v3dv_descriptor_set_binding_layout * layout)290 sha1_update_descriptor_set_binding_layout(struct mesa_sha1 *ctx,
291 const struct v3dv_descriptor_set_binding_layout *layout)
292 {
293 SHA1_UPDATE_VALUE(ctx, layout->type);
294 SHA1_UPDATE_VALUE(ctx, layout->array_size);
295 SHA1_UPDATE_VALUE(ctx, layout->descriptor_index);
296 SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count);
297 SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_index);
298 SHA1_UPDATE_VALUE(ctx, layout->descriptor_offset);
299 SHA1_UPDATE_VALUE(ctx, layout->immutable_samplers_offset);
300 }
301
302 static void
sha1_update_descriptor_set_layout(struct mesa_sha1 * ctx,const struct v3dv_descriptor_set_layout * layout)303 sha1_update_descriptor_set_layout(struct mesa_sha1 *ctx,
304 const struct v3dv_descriptor_set_layout *layout)
305 {
306 SHA1_UPDATE_VALUE(ctx, layout->flags);
307 SHA1_UPDATE_VALUE(ctx, layout->binding_count);
308 SHA1_UPDATE_VALUE(ctx, layout->shader_stages);
309 SHA1_UPDATE_VALUE(ctx, layout->descriptor_count);
310 SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count);
311
312 for (uint16_t i = 0; i < layout->binding_count; i++)
313 sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i]);
314 }
315
316
317 /*
318 * As anv and tu already points:
319 *
320 * "Pipeline layouts. These have nothing to do with the pipeline. They are
321 * just multiple descriptor set layouts pasted together."
322 */
323
324 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreatePipelineLayout(VkDevice _device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)325 v3dv_CreatePipelineLayout(VkDevice _device,
326 const VkPipelineLayoutCreateInfo *pCreateInfo,
327 const VkAllocationCallbacks *pAllocator,
328 VkPipelineLayout *pPipelineLayout)
329 {
330 V3DV_FROM_HANDLE(v3dv_device, device, _device);
331 struct v3dv_pipeline_layout *layout;
332
333 assert(pCreateInfo->sType ==
334 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
335
336 layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout),
337 VK_OBJECT_TYPE_PIPELINE_LAYOUT);
338 if (layout == NULL)
339 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
340
341 layout->num_sets = pCreateInfo->setLayoutCount;
342
343 uint32_t dynamic_offset_count = 0;
344 for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
345 V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout,
346 pCreateInfo->pSetLayouts[set]);
347 v3dv_descriptor_set_layout_ref(set_layout);
348 layout->set[set].layout = set_layout;
349 layout->set[set].dynamic_offset_start = dynamic_offset_count;
350 for (uint32_t b = 0; b < set_layout->binding_count; b++) {
351 dynamic_offset_count += set_layout->binding[b].array_size *
352 set_layout->binding[b].dynamic_offset_count;
353 }
354
355 layout->shader_stages |= set_layout->shader_stages;
356 }
357
358 layout->push_constant_size = 0;
359 for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
360 const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
361 layout->push_constant_size =
362 MAX2(layout->push_constant_size, range->offset + range->size);
363 }
364
365 layout->push_constant_size = align(layout->push_constant_size, 4096);
366
367 layout->dynamic_offset_count = dynamic_offset_count;
368
369 struct mesa_sha1 ctx;
370 _mesa_sha1_init(&ctx);
371 for (unsigned s = 0; s < layout->num_sets; s++) {
372 sha1_update_descriptor_set_layout(&ctx, layout->set[s].layout);
373 _mesa_sha1_update(&ctx, &layout->set[s].dynamic_offset_start,
374 sizeof(layout->set[s].dynamic_offset_start));
375 }
376 _mesa_sha1_update(&ctx, &layout->num_sets, sizeof(layout->num_sets));
377 _mesa_sha1_final(&ctx, layout->sha1);
378
379 *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout);
380
381 return VK_SUCCESS;
382 }
383
384 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyPipelineLayout(VkDevice _device,VkPipelineLayout _pipelineLayout,const VkAllocationCallbacks * pAllocator)385 v3dv_DestroyPipelineLayout(VkDevice _device,
386 VkPipelineLayout _pipelineLayout,
387 const VkAllocationCallbacks *pAllocator)
388 {
389 V3DV_FROM_HANDLE(v3dv_device, device, _device);
390 V3DV_FROM_HANDLE(v3dv_pipeline_layout, pipeline_layout, _pipelineLayout);
391
392 if (!pipeline_layout)
393 return;
394
395 for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
396 v3dv_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
397
398 vk_object_free(&device->vk, pAllocator, pipeline_layout);
399 }
400
401 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)402 v3dv_CreateDescriptorPool(VkDevice _device,
403 const VkDescriptorPoolCreateInfo *pCreateInfo,
404 const VkAllocationCallbacks *pAllocator,
405 VkDescriptorPool *pDescriptorPool)
406 {
407 V3DV_FROM_HANDLE(v3dv_device, device, _device);
408 struct v3dv_descriptor_pool *pool;
409 /* size is for the vulkan object descriptor pool. The final size would
410 * depend on some of FREE_DESCRIPTOR flags used
411 */
412 uint64_t size = sizeof(struct v3dv_descriptor_pool);
413 /* bo_size is for the descriptor related info that we need to have on a GPU
414 * address (so on v3dv_bo_alloc allocated memory), like for example the
415 * texture sampler state. Note that not all the descriptors use it
416 */
417 uint32_t bo_size = 0;
418 uint32_t descriptor_count = 0;
419
420 const VkDescriptorPoolInlineUniformBlockCreateInfo *inline_info =
421 vk_find_struct_const(pCreateInfo->pNext,
422 DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO);
423
424 for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
425 /* Verify supported descriptor type */
426 switch(pCreateInfo->pPoolSizes[i].type) {
427 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
428 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
429 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
430 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
431 case VK_DESCRIPTOR_TYPE_SAMPLER:
432 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
433 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
434 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
435 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
436 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
437 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
438 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
439 break;
440 default:
441 unreachable("Unimplemented descriptor type");
442 break;
443 }
444
445 assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0);
446 if (pCreateInfo->pPoolSizes[i].type ==
447 VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
448 /* Inline uniform blocks are specified to use the descriptor array
449 * size as the size in bytes of the block.
450 */
451 assert(inline_info);
452 descriptor_count += inline_info->maxInlineUniformBlockBindings;
453 bo_size += pCreateInfo->pPoolSizes[i].descriptorCount;
454 } else {
455 descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;
456 bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) *
457 pCreateInfo->pPoolSizes[i].descriptorCount;
458 }
459 }
460
461 /* We align all our buffers to V3D_NON_COHERENT_ATOM_SIZE, make sure we
462 * allocate enough memory to honor that requirement for all our inline
463 * buffers too.
464 */
465 if (inline_info) {
466 bo_size += V3D_NON_COHERENT_ATOM_SIZE *
467 inline_info->maxInlineUniformBlockBindings;
468 }
469
470 if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
471 uint64_t host_size =
472 pCreateInfo->maxSets * sizeof(struct v3dv_descriptor_set);
473 host_size += sizeof(struct v3dv_descriptor) * descriptor_count;
474 size += host_size;
475 } else {
476 size += sizeof(struct v3dv_descriptor_pool_entry) * pCreateInfo->maxSets;
477 }
478
479 pool = vk_object_zalloc(&device->vk, pAllocator, size,
480 VK_OBJECT_TYPE_DESCRIPTOR_POOL);
481
482 if (!pool)
483 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
484
485 if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
486 pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool);
487 pool->host_memory_ptr = pool->host_memory_base;
488 pool->host_memory_end = (uint8_t*)pool + size;
489 }
490
491 pool->max_entry_count = pCreateInfo->maxSets;
492
493 if (bo_size > 0) {
494 pool->bo = v3dv_bo_alloc(device, bo_size, "descriptor pool bo", true);
495 if (!pool->bo)
496 goto out_of_device_memory;
497
498 bool ok = v3dv_bo_map(device, pool->bo, pool->bo->size);
499 if (!ok)
500 goto out_of_device_memory;
501
502 pool->current_offset = 0;
503 } else {
504 pool->bo = NULL;
505 }
506
507 list_inithead(&pool->set_list);
508
509 *pDescriptorPool = v3dv_descriptor_pool_to_handle(pool);
510
511 return VK_SUCCESS;
512
513 out_of_device_memory:
514 vk_object_free(&device->vk, pAllocator, pool);
515 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
516 }
517
518 static void
descriptor_set_destroy(struct v3dv_device * device,struct v3dv_descriptor_pool * pool,struct v3dv_descriptor_set * set,bool free_bo)519 descriptor_set_destroy(struct v3dv_device *device,
520 struct v3dv_descriptor_pool *pool,
521 struct v3dv_descriptor_set *set,
522 bool free_bo)
523 {
524 assert(!pool->host_memory_base);
525
526 if (free_bo && !pool->host_memory_base) {
527 for (uint32_t i = 0; i < pool->entry_count; i++) {
528 if (pool->entries[i].set == set) {
529 memmove(&pool->entries[i], &pool->entries[i+1],
530 sizeof(pool->entries[i]) * (pool->entry_count - i - 1));
531 --pool->entry_count;
532 break;
533 }
534 }
535 }
536 vk_object_free(&device->vk, NULL, set);
537 }
538
539 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyDescriptorPool(VkDevice _device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)540 v3dv_DestroyDescriptorPool(VkDevice _device,
541 VkDescriptorPool _pool,
542 const VkAllocationCallbacks *pAllocator)
543 {
544 V3DV_FROM_HANDLE(v3dv_device, device, _device);
545 V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, _pool);
546
547 if (!pool)
548 return;
549
550 list_for_each_entry_safe(struct v3dv_descriptor_set, set,
551 &pool->set_list, pool_link) {
552 v3dv_descriptor_set_layout_unref(device, set->layout);
553 }
554
555 if (!pool->host_memory_base) {
556 for(int i = 0; i < pool->entry_count; ++i) {
557 descriptor_set_destroy(device, pool, pool->entries[i].set, false);
558 }
559 }
560
561 if (pool->bo) {
562 v3dv_bo_free(device, pool->bo);
563 pool->bo = NULL;
564 }
565
566 vk_object_free(&device->vk, pAllocator, pool);
567 }
568
569 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_ResetDescriptorPool(VkDevice _device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)570 v3dv_ResetDescriptorPool(VkDevice _device,
571 VkDescriptorPool descriptorPool,
572 VkDescriptorPoolResetFlags flags)
573 {
574 V3DV_FROM_HANDLE(v3dv_device, device, _device);
575 V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
576
577 list_for_each_entry_safe(struct v3dv_descriptor_set, set,
578 &pool->set_list, pool_link) {
579 v3dv_descriptor_set_layout_unref(device, set->layout);
580 }
581 list_inithead(&pool->set_list);
582
583 if (!pool->host_memory_base) {
584 for(int i = 0; i < pool->entry_count; ++i) {
585 descriptor_set_destroy(device, pool, pool->entries[i].set, false);
586 }
587 } else {
588 /* We clean-up the host memory, so when allocating a new set from the
589 * pool, it is already 0
590 */
591 uint32_t host_size = pool->host_memory_end - pool->host_memory_base;
592 memset(pool->host_memory_base, 0, host_size);
593 }
594
595 pool->entry_count = 0;
596 pool->host_memory_ptr = pool->host_memory_base;
597 pool->current_offset = 0;
598
599 return VK_SUCCESS;
600 }
601
602 void
v3dv_descriptor_set_layout_destroy(struct v3dv_device * device,struct v3dv_descriptor_set_layout * set_layout)603 v3dv_descriptor_set_layout_destroy(struct v3dv_device *device,
604 struct v3dv_descriptor_set_layout *set_layout)
605 {
606 assert(set_layout->ref_cnt == 0);
607 vk_object_base_finish(&set_layout->base);
608 vk_free2(&device->vk.alloc, NULL, set_layout);
609 }
610
611 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateDescriptorSetLayout(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)612 v3dv_CreateDescriptorSetLayout(VkDevice _device,
613 const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
614 const VkAllocationCallbacks *pAllocator,
615 VkDescriptorSetLayout *pSetLayout)
616 {
617 V3DV_FROM_HANDLE(v3dv_device, device, _device);
618 struct v3dv_descriptor_set_layout *set_layout;
619
620 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
621
622 uint32_t num_bindings = 0;
623 uint32_t immutable_sampler_count = 0;
624 for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
625 num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
626
627 /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
628 *
629 * "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
630 * VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
631 * pImmutableSamplers can be used to initialize a set of immutable
632 * samplers. [...] If descriptorType is not one of these descriptor
633 * types, then pImmutableSamplers is ignored.
634 *
635 * We need to be careful here and only parse pImmutableSamplers if we
636 * have one of the right descriptor types.
637 */
638 VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;
639 if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
640 desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) &&
641 pCreateInfo->pBindings[j].pImmutableSamplers) {
642 immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
643 }
644 }
645
646 /* We place immutable samplers after the binding data. We want to use
647 * offsetof instead of any sizeof(struct v3dv_descriptor_set_layout)
648 * because the latter may include padding at the end of the struct.
649 */
650 uint32_t samplers_offset =
651 offsetof(struct v3dv_descriptor_set_layout, binding[num_bindings]);
652
653 uint32_t size = samplers_offset +
654 immutable_sampler_count * sizeof(struct v3dv_sampler);
655
656 /* Descriptor set layouts are reference counted and therefore can survive
657 * vkDestroyPipelineSetLayout, so they need to be allocated with a device
658 * scope.
659 */
660 set_layout =
661 vk_zalloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
662 if (!set_layout)
663 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
664
665 vk_object_base_init(&device->vk, &set_layout->base,
666 VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
667
668 struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings];
669
670 assert(pCreateInfo->bindingCount == 0 || num_bindings > 0);
671
672 VkDescriptorSetLayoutBinding *bindings = NULL;
673 VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,
674 pCreateInfo->bindingCount, &bindings);
675 if (result != VK_SUCCESS) {
676 v3dv_descriptor_set_layout_destroy(device, set_layout);
677 return vk_error(device, result);
678 }
679
680 set_layout->binding_count = num_bindings;
681 set_layout->flags = pCreateInfo->flags;
682 set_layout->shader_stages = 0;
683 set_layout->bo_size = 0;
684 set_layout->ref_cnt = 1;
685
686 uint32_t descriptor_count = 0;
687 uint32_t dynamic_offset_count = 0;
688
689 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
690 const VkDescriptorSetLayoutBinding *binding = bindings + i;
691 uint32_t binding_number = binding->binding;
692
693 switch (binding->descriptorType) {
694 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
695 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
696 break;
697 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
698 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
699 set_layout->binding[binding_number].dynamic_offset_count = 1;
700 break;
701 case VK_DESCRIPTOR_TYPE_SAMPLER:
702 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
703 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
704 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
705 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
706 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
707 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
708 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
709 /* Nothing here, just to keep the descriptor type filtering below */
710 break;
711 default:
712 unreachable("Unknown descriptor type\n");
713 break;
714 }
715
716 set_layout->binding[binding_number].type = binding->descriptorType;
717 set_layout->binding[binding_number].array_size = binding->descriptorCount;
718 set_layout->binding[binding_number].descriptor_index = descriptor_count;
719 set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count;
720
721 if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
722 binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
723 binding->pImmutableSamplers) {
724
725 set_layout->binding[binding_number].immutable_samplers_offset = samplers_offset;
726
727 for (uint32_t i = 0; i < binding->descriptorCount; i++)
728 samplers[i] = *v3dv_sampler_from_handle(binding->pImmutableSamplers[i]);
729
730 samplers += binding->descriptorCount;
731 samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount;
732 }
733
734 set_layout->shader_stages |= binding->stageFlags;
735
736 if (binding->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
737 dynamic_offset_count += binding->descriptorCount *
738 set_layout->binding[binding_number].dynamic_offset_count;
739
740 descriptor_count += binding->descriptorCount;
741
742 set_layout->binding[binding_number].descriptor_offset =
743 set_layout->bo_size;
744 set_layout->bo_size +=
745 v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) *
746 binding->descriptorCount;
747 } else {
748 /* We align all our buffers, inline buffers too. We made sure to take
749 * this account when calculating total BO size requirements at pool
750 * creation time.
751 */
752 set_layout->bo_size = align(set_layout->bo_size,
753 V3D_NON_COHERENT_ATOM_SIZE);
754
755 set_layout->binding[binding_number].descriptor_offset =
756 set_layout->bo_size;
757
758 /* Inline uniform blocks are not arrayed, instead descriptorCount
759 * specifies the size of the buffer in bytes.
760 */
761 set_layout->bo_size += binding->descriptorCount;
762 descriptor_count++;
763 }
764 }
765
766 free(bindings);
767
768 set_layout->descriptor_count = descriptor_count;
769 set_layout->dynamic_offset_count = dynamic_offset_count;
770
771 *pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout);
772
773 return VK_SUCCESS;
774 }
775
776 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyDescriptorSetLayout(VkDevice _device,VkDescriptorSetLayout _set_layout,const VkAllocationCallbacks * pAllocator)777 v3dv_DestroyDescriptorSetLayout(VkDevice _device,
778 VkDescriptorSetLayout _set_layout,
779 const VkAllocationCallbacks *pAllocator)
780 {
781 V3DV_FROM_HANDLE(v3dv_device, device, _device);
782 V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, _set_layout);
783
784 if (!set_layout)
785 return;
786
787 v3dv_descriptor_set_layout_unref(device, set_layout);
788 }
789
790 static inline VkResult
out_of_pool_memory(const struct v3dv_device * device,const struct v3dv_descriptor_pool * pool)791 out_of_pool_memory(const struct v3dv_device *device,
792 const struct v3dv_descriptor_pool *pool)
793 {
794 /* Don't log OOPM errors for internal driver pools, we handle these properly
795 * by allocating a new pool, so they don't point to real issues.
796 */
797 if (!pool->is_driver_internal)
798 return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
799 else
800 return VK_ERROR_OUT_OF_POOL_MEMORY;
801 }
802
803 static VkResult
descriptor_set_create(struct v3dv_device * device,struct v3dv_descriptor_pool * pool,struct v3dv_descriptor_set_layout * layout,struct v3dv_descriptor_set ** out_set)804 descriptor_set_create(struct v3dv_device *device,
805 struct v3dv_descriptor_pool *pool,
806 struct v3dv_descriptor_set_layout *layout,
807 struct v3dv_descriptor_set **out_set)
808 {
809 struct v3dv_descriptor_set *set;
810 uint32_t descriptor_count = layout->descriptor_count;
811 unsigned mem_size = sizeof(struct v3dv_descriptor_set) +
812 sizeof(struct v3dv_descriptor) * descriptor_count;
813
814 if (pool->host_memory_base) {
815 if (pool->host_memory_end - pool->host_memory_ptr < mem_size)
816 return out_of_pool_memory(device, pool);
817
818 set = (struct v3dv_descriptor_set*)pool->host_memory_ptr;
819 pool->host_memory_ptr += mem_size;
820
821 vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
822 } else {
823 set = vk_object_zalloc(&device->vk, NULL, mem_size,
824 VK_OBJECT_TYPE_DESCRIPTOR_SET);
825
826 if (!set)
827 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
828 }
829
830 set->pool = pool;
831
832 set->layout = layout;
833
834 /* FIXME: VK_EXT_descriptor_indexing introduces
835 * VARIABLE_DESCRIPTOR_LAYOUT_COUNT. That would affect the layout_size used
836 * below for bo allocation
837 */
838
839 uint32_t offset = 0;
840 uint32_t index = pool->entry_count;
841
842 if (layout->bo_size) {
843 if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) {
844 vk_object_free(&device->vk, NULL, set);
845 return out_of_pool_memory(device, pool);
846 }
847
848 /* We first try to allocate linearly fist, so that we don't spend time
849 * looking for gaps if the app only allocates & resets via the pool.
850 *
851 * If that fails, we try to find a gap from previously freed subregions
852 * iterating through the descriptor pool entries. Note that we are not
853 * doing that if we have a pool->host_memory_base. We only have that if
854 * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT is not set, so in
855 * that case the user can't free subregions, so it doesn't make sense to
856 * even try (or track those subregions).
857 */
858 if (pool->current_offset + layout->bo_size <= pool->bo->size) {
859 offset = pool->current_offset;
860 pool->current_offset += layout->bo_size;
861 } else if (!pool->host_memory_base) {
862 for (index = 0; index < pool->entry_count; index++) {
863 if (pool->entries[index].offset - offset >= layout->bo_size)
864 break;
865 offset = pool->entries[index].offset + pool->entries[index].size;
866 }
867 if (pool->bo->size - offset < layout->bo_size) {
868 vk_object_free(&device->vk, NULL, set);
869 return out_of_pool_memory(device, pool);
870 }
871 memmove(&pool->entries[index + 1], &pool->entries[index],
872 sizeof(pool->entries[0]) * (pool->entry_count - index));
873 } else {
874 assert(pool->host_memory_base);
875 return out_of_pool_memory(device, pool);
876 }
877
878 set->base_offset = offset;
879 }
880
881 if (!pool->host_memory_base) {
882 pool->entries[index].set = set;
883 pool->entries[index].offset = offset;
884 pool->entries[index].size = layout->bo_size;
885 pool->entry_count++;
886 }
887
888 /* Go through and fill out immutable samplers if we have any */
889 for (uint32_t b = 0; b < layout->binding_count; b++) {
890 if (layout->binding[b].immutable_samplers_offset == 0)
891 continue;
892
893 const struct v3dv_sampler *samplers =
894 (const struct v3dv_sampler *)((const char *)layout +
895 layout->binding[b].immutable_samplers_offset);
896
897 for (uint32_t i = 0; i < layout->binding[b].array_size; i++) {
898 uint32_t combined_offset =
899 layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ?
900 v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0;
901
902 void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i);
903 desc_map += combined_offset;
904
905 memcpy(desc_map,
906 samplers[i].sampler_state,
907 sizeof(samplers[i].sampler_state));
908 }
909 }
910
911 v3dv_descriptor_set_layout_ref(layout);
912 list_addtail(&set->pool_link, &pool->set_list);
913
914 *out_set = set;
915
916 return VK_SUCCESS;
917 }
918
919 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_AllocateDescriptorSets(VkDevice _device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)920 v3dv_AllocateDescriptorSets(VkDevice _device,
921 const VkDescriptorSetAllocateInfo *pAllocateInfo,
922 VkDescriptorSet *pDescriptorSets)
923 {
924 V3DV_FROM_HANDLE(v3dv_device, device, _device);
925 V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, pAllocateInfo->descriptorPool);
926
927 VkResult result = VK_SUCCESS;
928 struct v3dv_descriptor_set *set = NULL;
929 uint32_t i = 0;
930
931 for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
932 V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, layout,
933 pAllocateInfo->pSetLayouts[i]);
934
935 result = descriptor_set_create(device, pool, layout, &set);
936 if (result != VK_SUCCESS)
937 break;
938
939 pDescriptorSets[i] = v3dv_descriptor_set_to_handle(set);
940 }
941
942 if (result != VK_SUCCESS) {
943 v3dv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
944 i, pDescriptorSets);
945 for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
946 pDescriptorSets[i] = VK_NULL_HANDLE;
947 }
948 }
949
950 return result;
951 }
952
953 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_FreeDescriptorSets(VkDevice _device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)954 v3dv_FreeDescriptorSets(VkDevice _device,
955 VkDescriptorPool descriptorPool,
956 uint32_t count,
957 const VkDescriptorSet *pDescriptorSets)
958 {
959 V3DV_FROM_HANDLE(v3dv_device, device, _device);
960 V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
961
962 for (uint32_t i = 0; i < count; i++) {
963 V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]);
964
965 if (set) {
966 v3dv_descriptor_set_layout_unref(device, set->layout);
967 list_del(&set->pool_link);
968 if (!pool->host_memory_base)
969 descriptor_set_destroy(device, pool, set, true);
970 }
971 }
972
973 return VK_SUCCESS;
974 }
975
976 static void
descriptor_bo_copy(struct v3dv_device * device,struct v3dv_descriptor_set * dst_set,const struct v3dv_descriptor_set_binding_layout * dst_binding_layout,uint32_t dst_array_index,struct v3dv_descriptor_set * src_set,const struct v3dv_descriptor_set_binding_layout * src_binding_layout,uint32_t src_array_index)977 descriptor_bo_copy(struct v3dv_device *device,
978 struct v3dv_descriptor_set *dst_set,
979 const struct v3dv_descriptor_set_binding_layout *dst_binding_layout,
980 uint32_t dst_array_index,
981 struct v3dv_descriptor_set *src_set,
982 const struct v3dv_descriptor_set_binding_layout *src_binding_layout,
983 uint32_t src_array_index)
984 {
985 assert(dst_binding_layout->type == src_binding_layout->type);
986
987 void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index);
988 void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index);
989
990 memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type));
991 }
992
993 static void
write_buffer_descriptor(struct v3dv_descriptor * descriptor,VkDescriptorType desc_type,const VkDescriptorBufferInfo * buffer_info)994 write_buffer_descriptor(struct v3dv_descriptor *descriptor,
995 VkDescriptorType desc_type,
996 const VkDescriptorBufferInfo *buffer_info)
997 {
998 V3DV_FROM_HANDLE(v3dv_buffer, buffer, buffer_info->buffer);
999
1000 descriptor->type = desc_type;
1001 descriptor->buffer = buffer;
1002 descriptor->offset = buffer_info->offset;
1003 if (buffer_info->range == VK_WHOLE_SIZE) {
1004 descriptor->range = buffer->size - buffer_info->offset;
1005 } else {
1006 assert(descriptor->range <= UINT32_MAX);
1007 descriptor->range = buffer_info->range;
1008 }
1009 }
1010
1011 static void
write_image_descriptor(struct v3dv_device * device,struct v3dv_descriptor * descriptor,VkDescriptorType desc_type,struct v3dv_descriptor_set * set,const struct v3dv_descriptor_set_binding_layout * binding_layout,struct v3dv_image_view * iview,struct v3dv_sampler * sampler,uint32_t array_index)1012 write_image_descriptor(struct v3dv_device *device,
1013 struct v3dv_descriptor *descriptor,
1014 VkDescriptorType desc_type,
1015 struct v3dv_descriptor_set *set,
1016 const struct v3dv_descriptor_set_binding_layout *binding_layout,
1017 struct v3dv_image_view *iview,
1018 struct v3dv_sampler *sampler,
1019 uint32_t array_index)
1020 {
1021 descriptor->type = desc_type;
1022 descriptor->sampler = sampler;
1023 descriptor->image_view = iview;
1024
1025 void *desc_map = descriptor_bo_map(device, set,
1026 binding_layout, array_index);
1027
1028 if (iview) {
1029 const uint32_t tex_state_index =
1030 iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ||
1031 desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1;
1032 memcpy(desc_map,
1033 iview->texture_shader_state[tex_state_index],
1034 sizeof(iview->texture_shader_state[0]));
1035 desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
1036 }
1037
1038 if (sampler && !binding_layout->immutable_samplers_offset) {
1039 /* For immutable samplers this was already done as part of the
1040 * descriptor set create, as that info can't change later
1041 */
1042 memcpy(desc_map,
1043 sampler->sampler_state,
1044 sizeof(sampler->sampler_state));
1045 }
1046 }
1047
1048
1049 static void
write_buffer_view_descriptor(struct v3dv_device * device,struct v3dv_descriptor * descriptor,VkDescriptorType desc_type,struct v3dv_descriptor_set * set,const struct v3dv_descriptor_set_binding_layout * binding_layout,struct v3dv_buffer_view * bview,uint32_t array_index)1050 write_buffer_view_descriptor(struct v3dv_device *device,
1051 struct v3dv_descriptor *descriptor,
1052 VkDescriptorType desc_type,
1053 struct v3dv_descriptor_set *set,
1054 const struct v3dv_descriptor_set_binding_layout *binding_layout,
1055 struct v3dv_buffer_view *bview,
1056 uint32_t array_index)
1057 {
1058 assert(bview);
1059 descriptor->type = desc_type;
1060 descriptor->buffer_view = bview;
1061
1062 void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index);
1063
1064 memcpy(desc_map,
1065 bview->texture_shader_state,
1066 sizeof(bview->texture_shader_state));
1067 }
1068
1069 static void
write_inline_uniform_descriptor(struct v3dv_device * device,struct v3dv_descriptor * descriptor,struct v3dv_descriptor_set * set,const struct v3dv_descriptor_set_binding_layout * binding_layout,const void * data,size_t offset,size_t size)1070 write_inline_uniform_descriptor(struct v3dv_device *device,
1071 struct v3dv_descriptor *descriptor,
1072 struct v3dv_descriptor_set *set,
1073 const struct v3dv_descriptor_set_binding_layout *binding_layout,
1074 const void *data,
1075 size_t offset,
1076 size_t size)
1077 {
1078 assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK);
1079 descriptor->type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
1080 descriptor->buffer = NULL;
1081
1082 void *desc_map = descriptor_bo_map(device, set, binding_layout, 0);
1083 memcpy(desc_map + offset, data, size);
1084
1085 /* Inline uniform buffers allocate BO space in the pool for all inline
1086 * buffers it may allocate and then this space is assigned to individual
1087 * descriptors when they are written, so we define the range of an inline
1088 * buffer as the largest range of data that the client has written to it.
1089 */
1090 descriptor->offset = 0;
1091 descriptor->range = MAX2(descriptor->range, offset + size);
1092 }
1093
1094 VKAPI_ATTR void VKAPI_CALL
v3dv_UpdateDescriptorSets(VkDevice _device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)1095 v3dv_UpdateDescriptorSets(VkDevice _device,
1096 uint32_t descriptorWriteCount,
1097 const VkWriteDescriptorSet *pDescriptorWrites,
1098 uint32_t descriptorCopyCount,
1099 const VkCopyDescriptorSet *pDescriptorCopies)
1100 {
1101 V3DV_FROM_HANDLE(v3dv_device, device, _device);
1102 for (uint32_t i = 0; i < descriptorWriteCount; i++) {
1103 const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
1104 V3DV_FROM_HANDLE(v3dv_descriptor_set, set, writeset->dstSet);
1105
1106 const struct v3dv_descriptor_set_binding_layout *binding_layout =
1107 set->layout->binding + writeset->dstBinding;
1108
1109 struct v3dv_descriptor *descriptor = set->descriptors;
1110
1111 descriptor += binding_layout->descriptor_index;
1112
1113 /* Inline uniform blocks are not arrayed, instead they use dstArrayElement
1114 * to specify the byte offset of the uniform update and descriptorCount
1115 * to specify the size (in bytes) of the update.
1116 */
1117 uint32_t descriptor_count;
1118 if (writeset->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1119 descriptor += writeset->dstArrayElement;
1120 descriptor_count = writeset->descriptorCount;
1121 } else {
1122 descriptor_count = 1;
1123 }
1124
1125 for (uint32_t j = 0; j < descriptor_count; ++j) {
1126 switch(writeset->descriptorType) {
1127
1128 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1129 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1130 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1131 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
1132 const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j;
1133 write_buffer_descriptor(descriptor, writeset->descriptorType,
1134 buffer_info);
1135 break;
1136 }
1137 case VK_DESCRIPTOR_TYPE_SAMPLER: {
1138 /* If we are here we shouldn't be modifying a immutable sampler,
1139 * so we don't ensure that would work or not crash. But let the
1140 * validation layers check that
1141 */
1142 const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1143 V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1144 write_image_descriptor(device, descriptor, writeset->descriptorType,
1145 set, binding_layout, NULL, sampler,
1146 writeset->dstArrayElement + j);
1147
1148 break;
1149 }
1150 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1151 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1152 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
1153 const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1154 V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1155 write_image_descriptor(device, descriptor, writeset->descriptorType,
1156 set, binding_layout, iview, NULL,
1157 writeset->dstArrayElement + j);
1158
1159 break;
1160 }
1161 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1162 const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1163 V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1164 V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1165 write_image_descriptor(device, descriptor, writeset->descriptorType,
1166 set, binding_layout, iview, sampler,
1167 writeset->dstArrayElement + j);
1168
1169 break;
1170 }
1171 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1172 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
1173 V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view,
1174 writeset->pTexelBufferView[j]);
1175 write_buffer_view_descriptor(device, descriptor, writeset->descriptorType,
1176 set, binding_layout, buffer_view,
1177 writeset->dstArrayElement + j);
1178 break;
1179 }
1180 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: {
1181 const VkWriteDescriptorSetInlineUniformBlock *inline_write =
1182 vk_find_struct_const(writeset->pNext,
1183 WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK);
1184 assert(inline_write->dataSize == writeset->descriptorCount);
1185 write_inline_uniform_descriptor(device, descriptor, set,
1186 binding_layout,
1187 inline_write->pData,
1188 writeset->dstArrayElement, /* offset */
1189 inline_write->dataSize);
1190 break;
1191 }
1192 default:
1193 unreachable("unimplemented descriptor type");
1194 break;
1195 }
1196 descriptor++;
1197 }
1198 }
1199
1200 for (uint32_t i = 0; i < descriptorCopyCount; i++) {
1201 const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];
1202 V3DV_FROM_HANDLE(v3dv_descriptor_set, src_set,
1203 copyset->srcSet);
1204 V3DV_FROM_HANDLE(v3dv_descriptor_set, dst_set,
1205 copyset->dstSet);
1206
1207 const struct v3dv_descriptor_set_binding_layout *src_binding_layout =
1208 src_set->layout->binding + copyset->srcBinding;
1209 const struct v3dv_descriptor_set_binding_layout *dst_binding_layout =
1210 dst_set->layout->binding + copyset->dstBinding;
1211
1212 assert(src_binding_layout->type == dst_binding_layout->type);
1213
1214 struct v3dv_descriptor *src_descriptor = src_set->descriptors;
1215 struct v3dv_descriptor *dst_descriptor = dst_set->descriptors;
1216
1217 src_descriptor += src_binding_layout->descriptor_index;
1218 dst_descriptor += dst_binding_layout->descriptor_index;
1219
1220 if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1221 /* {src,dst}ArrayElement specifies src/dst start offset and
1222 * descriptorCount specifies size (in bytes) to copy.
1223 */
1224 const void *src_data = src_set->pool->bo->map +
1225 src_set->base_offset +
1226 src_binding_layout->descriptor_offset +
1227 copyset->srcArrayElement;
1228 write_inline_uniform_descriptor(device, dst_descriptor, dst_set,
1229 dst_binding_layout,
1230 src_data,
1231 copyset->dstArrayElement,
1232 copyset->descriptorCount);
1233 continue;
1234 }
1235
1236 src_descriptor += copyset->srcArrayElement;
1237 dst_descriptor += copyset->dstArrayElement;
1238
1239 for (uint32_t j = 0; j < copyset->descriptorCount; j++) {
1240 *dst_descriptor = *src_descriptor;
1241 dst_descriptor++;
1242 src_descriptor++;
1243
1244 if (v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) > 0) {
1245 descriptor_bo_copy(device,
1246 dst_set, dst_binding_layout,
1247 j + copyset->dstArrayElement,
1248 src_set, src_binding_layout,
1249 j + copyset->srcArrayElement);
1250 }
1251
1252 }
1253 }
1254 }
1255
1256 VKAPI_ATTR void VKAPI_CALL
v3dv_GetDescriptorSetLayoutSupport(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)1257 v3dv_GetDescriptorSetLayoutSupport(
1258 VkDevice _device,
1259 const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
1260 VkDescriptorSetLayoutSupport *pSupport)
1261 {
1262 V3DV_FROM_HANDLE(v3dv_device, device, _device);
1263 VkDescriptorSetLayoutBinding *bindings = NULL;
1264 VkResult result = vk_create_sorted_bindings(
1265 pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
1266 if (result != VK_SUCCESS) {
1267 pSupport->supported = false;
1268 return;
1269 }
1270
1271 bool supported = true;
1272
1273 uint32_t desc_host_size = sizeof(struct v3dv_descriptor);
1274 uint32_t host_size = sizeof(struct v3dv_descriptor_set);
1275 uint32_t bo_size = 0;
1276 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
1277 const VkDescriptorSetLayoutBinding *binding = bindings + i;
1278
1279 if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) {
1280 supported = false;
1281 break;
1282 }
1283
1284 uint32_t desc_bo_size = v3dv_X(device, descriptor_bo_size)(binding->descriptorType);
1285 if (desc_bo_size > 0 &&
1286 (UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) {
1287 supported = false;
1288 break;
1289 }
1290
1291 host_size += binding->descriptorCount * desc_host_size;
1292 bo_size += binding->descriptorCount * desc_bo_size;
1293 }
1294
1295 free(bindings);
1296
1297 pSupport->supported = supported;
1298 }
1299
1300 VkResult
v3dv_CreateDescriptorUpdateTemplate(VkDevice _device,const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate)1301 v3dv_CreateDescriptorUpdateTemplate(
1302 VkDevice _device,
1303 const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
1304 const VkAllocationCallbacks *pAllocator,
1305 VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
1306 {
1307 V3DV_FROM_HANDLE(v3dv_device, device, _device);
1308 struct v3dv_descriptor_update_template *template;
1309
1310 size_t size = sizeof(*template) +
1311 pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]);
1312 template = vk_object_alloc(&device->vk, pAllocator, size,
1313 VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
1314 if (template == NULL)
1315 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1316
1317 template->bind_point = pCreateInfo->pipelineBindPoint;
1318
1319 assert(pCreateInfo->templateType ==
1320 VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
1321 template->set = pCreateInfo->set;
1322
1323 template->entry_count = pCreateInfo->descriptorUpdateEntryCount;
1324 for (uint32_t i = 0; i < template->entry_count; i++) {
1325 const VkDescriptorUpdateTemplateEntry *pEntry =
1326 &pCreateInfo->pDescriptorUpdateEntries[i];
1327
1328 template->entries[i] = (struct v3dv_descriptor_template_entry) {
1329 .type = pEntry->descriptorType,
1330 .binding = pEntry->dstBinding,
1331 .array_element = pEntry->dstArrayElement,
1332 .array_count = pEntry->descriptorCount,
1333 .offset = pEntry->offset,
1334 .stride = pEntry->stride,
1335 };
1336 }
1337
1338 *pDescriptorUpdateTemplate =
1339 v3dv_descriptor_update_template_to_handle(template);
1340
1341 return VK_SUCCESS;
1342 }
1343
1344 void
v3dv_DestroyDescriptorUpdateTemplate(VkDevice _device,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const VkAllocationCallbacks * pAllocator)1345 v3dv_DestroyDescriptorUpdateTemplate(
1346 VkDevice _device,
1347 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1348 const VkAllocationCallbacks *pAllocator)
1349 {
1350 V3DV_FROM_HANDLE(v3dv_device, device, _device);
1351 V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1352 descriptorUpdateTemplate);
1353
1354 if (!template)
1355 return;
1356
1357 vk_object_free(&device->vk, pAllocator, template);
1358 }
1359
1360 void
v3dv_UpdateDescriptorSetWithTemplate(VkDevice _device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)1361 v3dv_UpdateDescriptorSetWithTemplate(
1362 VkDevice _device,
1363 VkDescriptorSet descriptorSet,
1364 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1365 const void *pData)
1366 {
1367 V3DV_FROM_HANDLE(v3dv_device, device, _device);
1368 V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet);
1369 V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1370 descriptorUpdateTemplate);
1371
1372 for (int i = 0; i < template->entry_count; i++) {
1373 const struct v3dv_descriptor_template_entry *entry =
1374 &template->entries[i];
1375
1376 const struct v3dv_descriptor_set_binding_layout *binding_layout =
1377 set->layout->binding + entry->binding;
1378
1379 struct v3dv_descriptor *descriptor =
1380 set->descriptors +
1381 binding_layout->descriptor_index;
1382
1383 switch (entry->type) {
1384 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1385 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1386 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1387 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1388 for (uint32_t j = 0; j < entry->array_count; j++) {
1389 const VkDescriptorBufferInfo *info =
1390 pData + entry->offset + j * entry->stride;
1391 write_buffer_descriptor(descriptor + entry->array_element + j,
1392 entry->type, info);
1393 }
1394 break;
1395
1396 case VK_DESCRIPTOR_TYPE_SAMPLER:
1397 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1398 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1399 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1400 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1401 for (uint32_t j = 0; j < entry->array_count; j++) {
1402 const VkDescriptorImageInfo *info =
1403 pData + entry->offset + j * entry->stride;
1404 V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView);
1405 V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler);
1406 write_image_descriptor(device, descriptor + entry->array_element + j,
1407 entry->type, set, binding_layout, iview,
1408 sampler, entry->array_element + j);
1409 }
1410 break;
1411
1412 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1413 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1414 for (uint32_t j = 0; j < entry->array_count; j++) {
1415 const VkBufferView *_bview =
1416 pData + entry->offset + j * entry->stride;
1417 V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview);
1418 write_buffer_view_descriptor(device,
1419 descriptor + entry->array_element + j,
1420 entry->type, set, binding_layout, bview,
1421 entry->array_element + j);
1422 }
1423 break;
1424
1425 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: {
1426 write_inline_uniform_descriptor(device, descriptor, set,
1427 binding_layout,
1428 pData + entry->offset,
1429 entry->array_element, /* offset */
1430 entry->array_count); /* size */
1431 break;
1432 }
1433
1434 default:
1435 unreachable("Unsupported descriptor type");
1436 }
1437 }
1438 }
1439
1440 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateSamplerYcbcrConversion(VkDevice _device,const VkSamplerYcbcrConversionCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSamplerYcbcrConversion * pYcbcrConversion)1441 v3dv_CreateSamplerYcbcrConversion(
1442 VkDevice _device,
1443 const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1444 const VkAllocationCallbacks *pAllocator,
1445 VkSamplerYcbcrConversion *pYcbcrConversion)
1446 {
1447 unreachable("Ycbcr sampler conversion is not supported");
1448 return VK_SUCCESS;
1449 }
1450
1451 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroySamplerYcbcrConversion(VkDevice _device,VkSamplerYcbcrConversion YcbcrConversion,const VkAllocationCallbacks * pAllocator)1452 v3dv_DestroySamplerYcbcrConversion(
1453 VkDevice _device,
1454 VkSamplerYcbcrConversion YcbcrConversion,
1455 const VkAllocationCallbacks *pAllocator)
1456 {
1457 unreachable("Ycbcr sampler conversion is not supported");
1458 }
1459