• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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