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