xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_descriptor_set.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Valve Corporation
3  * Copyright 2024 Alyssa Rosenzweig
4  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5  * SPDX-License-Identifier: MIT
6  */
7 #include "hk_descriptor_set.h"
8 #include "asahi/lib/agx_bo.h"
9 #include "vulkan/vulkan_core.h"
10 
11 #include "hk_buffer.h"
12 #include "hk_buffer_view.h"
13 #include "hk_descriptor_set_layout.h"
14 #include "hk_device.h"
15 #include "hk_entrypoints.h"
16 #include "hk_image_view.h"
17 #include "hk_physical_device.h"
18 #include "hk_sampler.h"
19 
20 static inline uint32_t
align_u32(uint32_t v,uint32_t a)21 align_u32(uint32_t v, uint32_t a)
22 {
23    assert(a != 0 && a == (a & -a));
24    return (v + a - 1) & ~(a - 1);
25 }
26 
27 static inline void *
desc_ubo_data(struct hk_descriptor_set * set,uint32_t binding,uint32_t elem,uint32_t * size_out)28 desc_ubo_data(struct hk_descriptor_set *set, uint32_t binding, uint32_t elem,
29               uint32_t *size_out)
30 {
31    const struct hk_descriptor_set_binding_layout *binding_layout =
32       &set->layout->binding[binding];
33 
34    uint32_t offset = binding_layout->offset + elem * binding_layout->stride;
35    assert(offset < set->size);
36 
37    if (size_out != NULL)
38       *size_out = set->size - offset;
39 
40    return (char *)set->mapped_ptr + offset;
41 }
42 
43 static void
write_desc(struct hk_descriptor_set * set,uint32_t binding,uint32_t elem,const void * desc_data,size_t desc_size)44 write_desc(struct hk_descriptor_set *set, uint32_t binding, uint32_t elem,
45            const void *desc_data, size_t desc_size)
46 {
47    ASSERTED uint32_t dst_size;
48    void *dst = desc_ubo_data(set, binding, elem, &dst_size);
49    assert(desc_size <= dst_size);
50    memcpy(dst, desc_data, desc_size);
51 }
52 
53 static void
write_sampled_image_view_desc(struct hk_descriptor_set * set,const VkDescriptorImageInfo * const info,uint32_t binding,uint32_t elem,VkDescriptorType descriptor_type)54 write_sampled_image_view_desc(struct hk_descriptor_set *set,
55                               const VkDescriptorImageInfo *const info,
56                               uint32_t binding, uint32_t elem,
57                               VkDescriptorType descriptor_type)
58 {
59    struct hk_sampled_image_descriptor desc[3] = {};
60    assert(HK_NULL_TEX_OFFSET == 0 && "zero initialized so null descs implicit");
61 
62    uint8_t plane_count = 1;
63    bool ia = (descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
64 
65    if (descriptor_type != VK_DESCRIPTOR_TYPE_SAMPLER && info &&
66        info->imageView != VK_NULL_HANDLE) {
67       VK_FROM_HANDLE(hk_image_view, view, info->imageView);
68 
69       plane_count = view->plane_count;
70       for (uint8_t plane = 0; plane < plane_count; plane++) {
71          unsigned index = ia ? view->planes[plane].ia_desc_index
72                              : view->planes[plane].sampled_desc_index;
73 
74          assert(index < (1 << 20));
75          desc[plane].image_offset = index * HK_IMAGE_STRIDE;
76       }
77    }
78 
79    if (descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER ||
80        descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
81       const struct hk_descriptor_set_binding_layout *binding_layout =
82          &set->layout->binding[binding];
83 
84       struct hk_sampler *sampler;
85       if (binding_layout->immutable_samplers) {
86          sampler = binding_layout->immutable_samplers[elem];
87       } else {
88          sampler = hk_sampler_from_handle(info->sampler);
89       }
90 
91       if (sampler->has_border)
92          assert(plane_count == 1);
93       else
94          plane_count = MAX2(plane_count, sampler->plane_count);
95 
96       for (uint8_t plane = 0; plane < plane_count; plane++) {
97          /* We need to replicate the last sampler plane out to all image
98           * planes due to sampler table entry limitations. See
99           * hk_CreateSampler in hk_sampler.c for more details.
100           */
101          uint8_t sampler_plane = MIN2(plane, sampler->plane_count - 1);
102          assert(sampler->planes[sampler_plane].hw->index < (1 << 12));
103 
104          /* All bindless samplers are indexed from 28 in hardware, add here so
105           * we don't have to care in the shader.
106           */
107          desc[plane].sampler_index =
108             sampler->planes[sampler_plane].hw->index + 28;
109          desc[plane].lod_bias_fp16 = sampler->lod_bias_fp16;
110          desc[plane].has_border = sampler->has_border;
111       }
112 
113       if (sampler->has_border) {
114          assert(sampler->plane_count == 2);
115          desc[0].clamp_0_sampler_index = sampler->planes[1].hw->index + 28;
116 
117          static_assert(sizeof(desc[0].border) == sizeof(sampler->custom_border),
118                        "fixed format");
119 
120          memcpy(desc[0].border, sampler->custom_border.uint32,
121                 sizeof(sampler->custom_border));
122       }
123    }
124    write_desc(set, binding, elem, desc, sizeof(desc[0]) * plane_count);
125 }
126 
127 static void
write_storage_image_view_desc(struct hk_descriptor_set * set,const VkDescriptorImageInfo * const info,uint32_t binding,uint32_t elem)128 write_storage_image_view_desc(struct hk_descriptor_set *set,
129                               const VkDescriptorImageInfo *const info,
130                               uint32_t binding, uint32_t elem)
131 {
132    struct hk_storage_image_descriptor desc = {};
133 
134    if (info && info->imageView != VK_NULL_HANDLE) {
135       VK_FROM_HANDLE(hk_image_view, view, info->imageView);
136 
137       /* Storage images are always single plane */
138       assert(view->plane_count == 1);
139       uint8_t plane = 0;
140 
141       desc.tex_offset =
142          view->planes[plane].ro_storage_desc_index * HK_IMAGE_STRIDE;
143 
144       desc.pbe_offset =
145          view->planes[plane].storage_desc_index * HK_IMAGE_STRIDE;
146    } else {
147       desc.tex_offset = HK_NULL_TEX_OFFSET;
148       desc.pbe_offset = HK_NULL_PBE_OFFSET;
149    }
150 
151    write_desc(set, binding, elem, &desc, sizeof(desc));
152 }
153 
154 static void
write_buffer_desc(struct hk_descriptor_set * set,const VkDescriptorBufferInfo * const info,uint32_t binding,uint32_t elem)155 write_buffer_desc(struct hk_descriptor_set *set,
156                   const VkDescriptorBufferInfo *const info, uint32_t binding,
157                   uint32_t elem)
158 {
159    VK_FROM_HANDLE(hk_buffer, buffer, info->buffer);
160 
161    const struct hk_addr_range addr_range =
162       hk_buffer_addr_range(buffer, info->offset, info->range);
163    assert(addr_range.range <= UINT32_MAX);
164 
165    const struct hk_buffer_address desc = {
166       .base_addr = addr_range.addr,
167       .size = addr_range.range,
168    };
169    write_desc(set, binding, elem, &desc, sizeof(desc));
170 }
171 
172 static void
write_dynamic_buffer_desc(struct hk_descriptor_set * set,const VkDescriptorBufferInfo * const info,uint32_t binding,uint32_t elem)173 write_dynamic_buffer_desc(struct hk_descriptor_set *set,
174                           const VkDescriptorBufferInfo *const info,
175                           uint32_t binding, uint32_t elem)
176 {
177    VK_FROM_HANDLE(hk_buffer, buffer, info->buffer);
178    const struct hk_descriptor_set_binding_layout *binding_layout =
179       &set->layout->binding[binding];
180 
181    const struct hk_addr_range addr_range =
182       hk_buffer_addr_range(buffer, info->offset, info->range);
183    assert(addr_range.range <= UINT32_MAX);
184 
185    struct hk_buffer_address *desc =
186       &set->dynamic_buffers[binding_layout->dynamic_buffer_index + elem];
187    *desc = (struct hk_buffer_address){
188       .base_addr = addr_range.addr,
189       .size = addr_range.range,
190    };
191 }
192 
193 static void
write_buffer_view_desc(struct hk_descriptor_set * set,const VkBufferView bufferView,uint32_t binding,uint32_t elem)194 write_buffer_view_desc(struct hk_descriptor_set *set,
195                        const VkBufferView bufferView, uint32_t binding,
196                        uint32_t elem)
197 {
198    struct hk_buffer_view_descriptor desc = {};
199    if (bufferView != VK_NULL_HANDLE) {
200       VK_FROM_HANDLE(hk_buffer_view, view, bufferView);
201 
202       assert(view->tex_desc_index < (1 << 20));
203       assert(view->pbe_desc_index < (1 << 20));
204 
205       desc.tex_offset = view->tex_desc_index * HK_IMAGE_STRIDE;
206       desc.pbe_offset = view->pbe_desc_index * HK_IMAGE_STRIDE;
207    } else {
208       desc.tex_offset = HK_NULL_TEX_OFFSET;
209       desc.pbe_offset = HK_NULL_PBE_OFFSET;
210    }
211 
212    write_desc(set, binding, elem, &desc, sizeof(desc));
213 }
214 
215 static void
write_inline_uniform_data(struct hk_descriptor_set * set,const VkWriteDescriptorSetInlineUniformBlock * info,uint32_t binding,uint32_t offset)216 write_inline_uniform_data(struct hk_descriptor_set *set,
217                           const VkWriteDescriptorSetInlineUniformBlock *info,
218                           uint32_t binding, uint32_t offset)
219 {
220    assert(set->layout->binding[binding].stride == 1);
221    write_desc(set, binding, offset, info->pData, info->dataSize);
222 }
223 
224 VKAPI_ATTR void VKAPI_CALL
hk_UpdateDescriptorSets(VkDevice device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)225 hk_UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
226                         const VkWriteDescriptorSet *pDescriptorWrites,
227                         uint32_t descriptorCopyCount,
228                         const VkCopyDescriptorSet *pDescriptorCopies)
229 {
230    for (uint32_t w = 0; w < descriptorWriteCount; w++) {
231       const VkWriteDescriptorSet *write = &pDescriptorWrites[w];
232       VK_FROM_HANDLE(hk_descriptor_set, set, write->dstSet);
233 
234       switch (write->descriptorType) {
235       case VK_DESCRIPTOR_TYPE_SAMPLER:
236       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
237       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
238       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
239          for (uint32_t j = 0; j < write->descriptorCount; j++) {
240             write_sampled_image_view_desc(
241                set, write->pImageInfo + j, write->dstBinding,
242                write->dstArrayElement + j, write->descriptorType);
243          }
244          break;
245 
246       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
247          for (uint32_t j = 0; j < write->descriptorCount; j++) {
248             write_storage_image_view_desc(set, write->pImageInfo + j,
249                                           write->dstBinding,
250                                           write->dstArrayElement + j);
251          }
252          break;
253 
254       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
255       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
256          for (uint32_t j = 0; j < write->descriptorCount; j++) {
257             write_buffer_view_desc(set, write->pTexelBufferView[j],
258                                    write->dstBinding,
259                                    write->dstArrayElement + j);
260          }
261          break;
262 
263       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
264       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
265          for (uint32_t j = 0; j < write->descriptorCount; j++) {
266             write_buffer_desc(set, write->pBufferInfo + j, write->dstBinding,
267                               write->dstArrayElement + j);
268          }
269          break;
270 
271       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
272       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
273          for (uint32_t j = 0; j < write->descriptorCount; j++) {
274             write_dynamic_buffer_desc(set, write->pBufferInfo + j,
275                                       write->dstBinding,
276                                       write->dstArrayElement + j);
277          }
278          break;
279 
280       case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: {
281          const VkWriteDescriptorSetInlineUniformBlock *write_inline =
282             vk_find_struct_const(write->pNext,
283                                  WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK);
284          assert(write_inline->dataSize == write->descriptorCount);
285          write_inline_uniform_data(set, write_inline, write->dstBinding,
286                                    write->dstArrayElement);
287          break;
288       }
289 
290       default:
291          break;
292       }
293    }
294 
295    for (uint32_t i = 0; i < descriptorCopyCount; i++) {
296       const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];
297       VK_FROM_HANDLE(hk_descriptor_set, src, copy->srcSet);
298       VK_FROM_HANDLE(hk_descriptor_set, dst, copy->dstSet);
299 
300       const struct hk_descriptor_set_binding_layout *src_binding_layout =
301          &src->layout->binding[copy->srcBinding];
302       const struct hk_descriptor_set_binding_layout *dst_binding_layout =
303          &dst->layout->binding[copy->dstBinding];
304 
305       if (dst_binding_layout->stride > 0 && src_binding_layout->stride > 0) {
306          for (uint32_t j = 0; j < copy->descriptorCount; j++) {
307             ASSERTED uint32_t dst_max_size, src_max_size;
308             void *dst_map = desc_ubo_data(
309                dst, copy->dstBinding, copy->dstArrayElement + j, &dst_max_size);
310             const void *src_map = desc_ubo_data(
311                src, copy->srcBinding, copy->srcArrayElement + j, &src_max_size);
312             const uint32_t copy_size =
313                MIN2(dst_binding_layout->stride, src_binding_layout->stride);
314             assert(copy_size <= dst_max_size && copy_size <= src_max_size);
315             memcpy(dst_map, src_map, copy_size);
316          }
317       }
318 
319       switch (src_binding_layout->type) {
320       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
321       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
322          const uint32_t dst_dyn_start =
323             dst_binding_layout->dynamic_buffer_index + copy->dstArrayElement;
324          const uint32_t src_dyn_start =
325             src_binding_layout->dynamic_buffer_index + copy->srcArrayElement;
326          typed_memcpy(&dst->dynamic_buffers[dst_dyn_start],
327                       &src->dynamic_buffers[src_dyn_start],
328                       copy->descriptorCount);
329          break;
330       }
331       default:
332          break;
333       }
334    }
335 }
336 
337 void
hk_push_descriptor_set_update(struct hk_push_descriptor_set * push_set,struct hk_descriptor_set_layout * layout,uint32_t write_count,const VkWriteDescriptorSet * writes)338 hk_push_descriptor_set_update(struct hk_push_descriptor_set *push_set,
339                               struct hk_descriptor_set_layout *layout,
340                               uint32_t write_count,
341                               const VkWriteDescriptorSet *writes)
342 {
343    assert(layout->non_variable_descriptor_buffer_size < sizeof(push_set->data));
344    struct hk_descriptor_set set = {
345       .layout = layout,
346       .size = sizeof(push_set->data),
347       .mapped_ptr = push_set->data,
348    };
349 
350    for (uint32_t w = 0; w < write_count; w++) {
351       const VkWriteDescriptorSet *write = &writes[w];
352       assert(write->dstSet == VK_NULL_HANDLE);
353 
354       switch (write->descriptorType) {
355       case VK_DESCRIPTOR_TYPE_SAMPLER:
356       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
357       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
358       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
359          for (uint32_t j = 0; j < write->descriptorCount; j++) {
360             write_sampled_image_view_desc(
361                &set, write->pImageInfo + j, write->dstBinding,
362                write->dstArrayElement + j, write->descriptorType);
363          }
364          break;
365 
366       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
367          for (uint32_t j = 0; j < write->descriptorCount; j++) {
368             write_storage_image_view_desc(&set, write->pImageInfo + j,
369                                           write->dstBinding,
370                                           write->dstArrayElement + j);
371          }
372          break;
373 
374       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
375       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
376          for (uint32_t j = 0; j < write->descriptorCount; j++) {
377             write_buffer_view_desc(&set, write->pTexelBufferView[j],
378                                    write->dstBinding,
379                                    write->dstArrayElement + j);
380          }
381          break;
382 
383       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
384       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
385          for (uint32_t j = 0; j < write->descriptorCount; j++) {
386             write_buffer_desc(&set, write->pBufferInfo + j, write->dstBinding,
387                               write->dstArrayElement + j);
388          }
389          break;
390 
391       default:
392          break;
393       }
394    }
395 }
396 
397 static void hk_descriptor_pool_free(struct hk_descriptor_pool *pool,
398                                     uint64_t addr, uint64_t size);
399 
400 static void
hk_descriptor_set_destroy(struct hk_device * dev,struct hk_descriptor_pool * pool,struct hk_descriptor_set * set)401 hk_descriptor_set_destroy(struct hk_device *dev,
402                           struct hk_descriptor_pool *pool,
403                           struct hk_descriptor_set *set)
404 {
405    list_del(&set->link);
406    if (set->size > 0)
407       hk_descriptor_pool_free(pool, set->addr, set->size);
408    vk_descriptor_set_layout_unref(&dev->vk, &set->layout->vk);
409 
410    vk_object_free(&dev->vk, NULL, set);
411 }
412 
413 static void
hk_destroy_descriptor_pool(struct hk_device * dev,const VkAllocationCallbacks * pAllocator,struct hk_descriptor_pool * pool)414 hk_destroy_descriptor_pool(struct hk_device *dev,
415                            const VkAllocationCallbacks *pAllocator,
416                            struct hk_descriptor_pool *pool)
417 {
418    list_for_each_entry_safe(struct hk_descriptor_set, set, &pool->sets, link)
419       hk_descriptor_set_destroy(dev, pool, set);
420 
421    util_vma_heap_finish(&pool->heap);
422    agx_bo_unreference(&dev->dev, pool->bo);
423 
424    vk_object_free(&dev->vk, pAllocator, pool);
425 }
426 
427 VKAPI_ATTR VkResult VKAPI_CALL
hk_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)428 hk_CreateDescriptorPool(VkDevice _device,
429                         const VkDescriptorPoolCreateInfo *pCreateInfo,
430                         const VkAllocationCallbacks *pAllocator,
431                         VkDescriptorPool *pDescriptorPool)
432 {
433    VK_FROM_HANDLE(hk_device, dev, _device);
434    struct hk_physical_device *pdev = hk_device_physical(dev);
435    struct hk_descriptor_pool *pool;
436 
437    pool = vk_object_zalloc(&dev->vk, pAllocator, sizeof(*pool),
438                            VK_OBJECT_TYPE_DESCRIPTOR_POOL);
439    if (!pool)
440       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
441 
442    list_inithead(&pool->sets);
443 
444    const VkMutableDescriptorTypeCreateInfoEXT *mutable_info =
445       vk_find_struct_const(pCreateInfo->pNext,
446                            MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT);
447 
448    uint32_t max_align = 0;
449    for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
450       const VkMutableDescriptorTypeListEXT *type_list = NULL;
451       if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_EXT &&
452           mutable_info && i < mutable_info->mutableDescriptorTypeListCount)
453          type_list = &mutable_info->pMutableDescriptorTypeLists[i];
454 
455       uint32_t stride, alignment;
456       hk_descriptor_stride_align_for_type(pdev, pCreateInfo->pPoolSizes[i].type,
457                                           type_list, &stride, &alignment);
458       max_align = MAX2(max_align, alignment);
459    }
460 
461    uint64_t bo_size = 0;
462    for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
463       const VkMutableDescriptorTypeListEXT *type_list = NULL;
464       if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_EXT &&
465           mutable_info && i < mutable_info->mutableDescriptorTypeListCount)
466          type_list = &mutable_info->pMutableDescriptorTypeLists[i];
467 
468       uint32_t stride, alignment;
469       hk_descriptor_stride_align_for_type(pdev, pCreateInfo->pPoolSizes[i].type,
470                                           type_list, &stride, &alignment);
471       bo_size +=
472          MAX2(stride, max_align) * pCreateInfo->pPoolSizes[i].descriptorCount;
473    }
474 
475    /* Individual descriptor sets are aligned to the min UBO alignment to
476     * ensure that we don't end up with unaligned data access in any shaders.
477     * This means that each descriptor buffer allocated may burn up to 16B of
478     * extra space to get the right alignment.  (Technically, it's at most 28B
479     * because we're always going to start at least 4B aligned but we're being
480     * conservative here.)  Allocate enough extra space that we can chop it
481     * into maxSets pieces and align each one of them to 32B.
482     */
483    bo_size += HK_MIN_UBO_ALIGNMENT * pCreateInfo->maxSets;
484 
485    if (bo_size) {
486       pool->bo = agx_bo_create(&dev->dev, bo_size, 0, 0, "Descriptor pool");
487       if (!pool->bo) {
488          hk_destroy_descriptor_pool(dev, pAllocator, pool);
489          return vk_error(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY);
490       }
491 
492       pool->mapped_ptr = pool->bo->map;
493 
494       /* The BO may be larger thanks to GPU page alignment.  We may as well
495        * make that extra space available to the client.
496        */
497       assert(pool->bo->size >= bo_size);
498       util_vma_heap_init(&pool->heap, pool->bo->va->addr, pool->bo->size);
499    } else {
500       util_vma_heap_init(&pool->heap, 0, 0);
501    }
502 
503    *pDescriptorPool = hk_descriptor_pool_to_handle(pool);
504    return VK_SUCCESS;
505 }
506 
507 static VkResult
hk_descriptor_pool_alloc(struct hk_descriptor_pool * pool,uint64_t size,uint64_t alignment,uint64_t * addr_out,void ** map_out)508 hk_descriptor_pool_alloc(struct hk_descriptor_pool *pool, uint64_t size,
509                          uint64_t alignment, uint64_t *addr_out, void **map_out)
510 {
511    assert(size > 0);
512    uint64_t addr = util_vma_heap_alloc(&pool->heap, size, alignment);
513    if (addr == 0)
514       return VK_ERROR_OUT_OF_POOL_MEMORY;
515 
516    assert(addr >= pool->bo->va->addr);
517    assert(addr + size <= pool->bo->va->addr + pool->bo->size);
518    uint64_t offset = addr - pool->bo->va->addr;
519 
520    *addr_out = addr;
521    *map_out = pool->mapped_ptr + offset;
522 
523    return VK_SUCCESS;
524 }
525 
526 static void
hk_descriptor_pool_free(struct hk_descriptor_pool * pool,uint64_t addr,uint64_t size)527 hk_descriptor_pool_free(struct hk_descriptor_pool *pool, uint64_t addr,
528                         uint64_t size)
529 {
530    assert(size > 0);
531    assert(addr >= pool->bo->va->addr);
532    assert(addr + size <= pool->bo->va->addr + pool->bo->size);
533    util_vma_heap_free(&pool->heap, addr, size);
534 }
535 
536 static VkResult
hk_descriptor_set_create(struct hk_device * dev,struct hk_descriptor_pool * pool,struct hk_descriptor_set_layout * layout,uint32_t variable_count,struct hk_descriptor_set ** out_set)537 hk_descriptor_set_create(struct hk_device *dev, struct hk_descriptor_pool *pool,
538                          struct hk_descriptor_set_layout *layout,
539                          uint32_t variable_count,
540                          struct hk_descriptor_set **out_set)
541 {
542    struct hk_descriptor_set *set;
543    VkResult result;
544 
545    uint32_t mem_size =
546       sizeof(struct hk_descriptor_set) +
547       layout->dynamic_buffer_count * sizeof(struct hk_buffer_address);
548 
549    set =
550       vk_object_zalloc(&dev->vk, NULL, mem_size, VK_OBJECT_TYPE_DESCRIPTOR_SET);
551    if (!set)
552       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
553 
554    set->size = layout->non_variable_descriptor_buffer_size;
555 
556    if (layout->binding_count > 0 &&
557        (layout->binding[layout->binding_count - 1].flags &
558         VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) {
559       uint32_t stride = layout->binding[layout->binding_count - 1].stride;
560 
561       /* Off by one so we don't underallocate the end. Otherwise vkd3d-proton
562        * descriptor-performance underallocates.
563        */
564       set->size += stride * (variable_count + 1);
565    }
566 
567    set->size = align64(set->size, HK_MIN_UBO_ALIGNMENT);
568 
569    if (set->size > 0) {
570       result = hk_descriptor_pool_alloc(pool, set->size, HK_MIN_UBO_ALIGNMENT,
571                                         &set->addr, &set->mapped_ptr);
572       if (result != VK_SUCCESS) {
573          vk_object_free(&dev->vk, NULL, set);
574          return result;
575       }
576    }
577 
578    vk_descriptor_set_layout_ref(&layout->vk);
579    set->layout = layout;
580 
581    for (uint32_t b = 0; b < layout->binding_count; b++) {
582       if (layout->binding[b].type != VK_DESCRIPTOR_TYPE_SAMPLER &&
583           layout->binding[b].type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
584          continue;
585 
586       if (layout->binding[b].immutable_samplers == NULL)
587          continue;
588 
589       uint32_t array_size = layout->binding[b].array_size;
590       if (layout->binding[b].flags &
591           VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)
592          array_size = variable_count;
593 
594       for (uint32_t j = 0; j < array_size; j++) {
595          write_sampled_image_view_desc(set, NULL, b, j,
596                                        layout->binding[b].type);
597       }
598    }
599 
600    list_addtail(&set->link, &pool->sets);
601    *out_set = set;
602 
603    return VK_SUCCESS;
604 }
605 
606 VKAPI_ATTR VkResult VKAPI_CALL
hk_AllocateDescriptorSets(VkDevice device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)607 hk_AllocateDescriptorSets(VkDevice device,
608                           const VkDescriptorSetAllocateInfo *pAllocateInfo,
609                           VkDescriptorSet *pDescriptorSets)
610 {
611    VK_FROM_HANDLE(hk_device, dev, device);
612    VK_FROM_HANDLE(hk_descriptor_pool, pool, pAllocateInfo->descriptorPool);
613 
614    VkResult result = VK_SUCCESS;
615    uint32_t i;
616 
617    struct hk_descriptor_set *set = NULL;
618 
619    const VkDescriptorSetVariableDescriptorCountAllocateInfo *var_desc_count =
620       vk_find_struct_const(
621          pAllocateInfo->pNext,
622          DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
623 
624    /* allocate a set of buffers for each shader to contain descriptors */
625    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
626       VK_FROM_HANDLE(hk_descriptor_set_layout, layout,
627                      pAllocateInfo->pSetLayouts[i]);
628       /* If descriptorSetCount is zero or this structure is not included in
629        * the pNext chain, then the variable lengths are considered to be zero.
630        */
631       const uint32_t variable_count =
632          var_desc_count && var_desc_count->descriptorSetCount > 0
633             ? var_desc_count->pDescriptorCounts[i]
634             : 0;
635 
636       result =
637          hk_descriptor_set_create(dev, pool, layout, variable_count, &set);
638       if (result != VK_SUCCESS)
639          break;
640 
641       pDescriptorSets[i] = hk_descriptor_set_to_handle(set);
642    }
643 
644    if (result != VK_SUCCESS) {
645       hk_FreeDescriptorSets(device, pAllocateInfo->descriptorPool, i,
646                             pDescriptorSets);
647       for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
648          pDescriptorSets[i] = VK_NULL_HANDLE;
649       }
650    }
651    return result;
652 }
653 
654 VKAPI_ATTR VkResult VKAPI_CALL
hk_FreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets)655 hk_FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
656                       uint32_t descriptorSetCount,
657                       const VkDescriptorSet *pDescriptorSets)
658 {
659    VK_FROM_HANDLE(hk_device, dev, device);
660    VK_FROM_HANDLE(hk_descriptor_pool, pool, descriptorPool);
661 
662    for (uint32_t i = 0; i < descriptorSetCount; i++) {
663       VK_FROM_HANDLE(hk_descriptor_set, set, pDescriptorSets[i]);
664 
665       if (set)
666          hk_descriptor_set_destroy(dev, pool, set);
667    }
668    return VK_SUCCESS;
669 }
670 
671 VKAPI_ATTR void VKAPI_CALL
hk_DestroyDescriptorPool(VkDevice device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)672 hk_DestroyDescriptorPool(VkDevice device, VkDescriptorPool _pool,
673                          const VkAllocationCallbacks *pAllocator)
674 {
675    VK_FROM_HANDLE(hk_device, dev, device);
676    VK_FROM_HANDLE(hk_descriptor_pool, pool, _pool);
677 
678    if (!_pool)
679       return;
680 
681    hk_destroy_descriptor_pool(dev, pAllocator, pool);
682 }
683 
684 VKAPI_ATTR VkResult VKAPI_CALL
hk_ResetDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)685 hk_ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
686                        VkDescriptorPoolResetFlags flags)
687 {
688    VK_FROM_HANDLE(hk_device, dev, device);
689    VK_FROM_HANDLE(hk_descriptor_pool, pool, descriptorPool);
690 
691    list_for_each_entry_safe(struct hk_descriptor_set, set, &pool->sets, link)
692       hk_descriptor_set_destroy(dev, pool, set);
693 
694    return VK_SUCCESS;
695 }
696 
697 static void
hk_descriptor_set_write_template(struct hk_descriptor_set * set,const struct vk_descriptor_update_template * template,const void * data)698 hk_descriptor_set_write_template(
699    struct hk_descriptor_set *set,
700    const struct vk_descriptor_update_template *template, const void *data)
701 {
702    for (uint32_t i = 0; i < template->entry_count; i++) {
703       const struct vk_descriptor_template_entry *entry = &template->entries[i];
704 
705       switch (entry->type) {
706       case VK_DESCRIPTOR_TYPE_SAMPLER:
707       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
708       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
709       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
710          for (uint32_t j = 0; j < entry->array_count; j++) {
711             const VkDescriptorImageInfo *info =
712                data + entry->offset + j * entry->stride;
713 
714             write_sampled_image_view_desc(set, info, entry->binding,
715                                           entry->array_element + j,
716                                           entry->type);
717          }
718          break;
719 
720       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
721          for (uint32_t j = 0; j < entry->array_count; j++) {
722             const VkDescriptorImageInfo *info =
723                data + entry->offset + j * entry->stride;
724 
725             write_storage_image_view_desc(set, info, entry->binding,
726                                           entry->array_element + j);
727          }
728          break;
729 
730       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
731       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
732          for (uint32_t j = 0; j < entry->array_count; j++) {
733             const VkBufferView *bview =
734                data + entry->offset + j * entry->stride;
735 
736             write_buffer_view_desc(set, *bview, entry->binding,
737                                    entry->array_element + j);
738          }
739          break;
740 
741       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
742       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
743          for (uint32_t j = 0; j < entry->array_count; j++) {
744             const VkDescriptorBufferInfo *info =
745                data + entry->offset + j * entry->stride;
746 
747             write_buffer_desc(set, info, entry->binding,
748                               entry->array_element + j);
749          }
750          break;
751 
752       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
753       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
754          for (uint32_t j = 0; j < entry->array_count; j++) {
755             const VkDescriptorBufferInfo *info =
756                data + entry->offset + j * entry->stride;
757 
758             write_dynamic_buffer_desc(set, info, entry->binding,
759                                       entry->array_element + j);
760          }
761          break;
762 
763       case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
764          write_desc(set, entry->binding, entry->array_element,
765                     data + entry->offset, entry->array_count);
766          break;
767 
768       default:
769          break;
770       }
771    }
772 }
773 
774 VKAPI_ATTR void VKAPI_CALL
hk_UpdateDescriptorSetWithTemplate(VkDevice device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)775 hk_UpdateDescriptorSetWithTemplate(
776    VkDevice device, VkDescriptorSet descriptorSet,
777    VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void *pData)
778 {
779    VK_FROM_HANDLE(hk_descriptor_set, set, descriptorSet);
780    VK_FROM_HANDLE(vk_descriptor_update_template, template,
781                   descriptorUpdateTemplate);
782 
783    hk_descriptor_set_write_template(set, template, pData);
784 }
785 
786 void
hk_push_descriptor_set_update_template(struct hk_push_descriptor_set * push_set,struct hk_descriptor_set_layout * layout,const struct vk_descriptor_update_template * template,const void * data)787 hk_push_descriptor_set_update_template(
788    struct hk_push_descriptor_set *push_set,
789    struct hk_descriptor_set_layout *layout,
790    const struct vk_descriptor_update_template *template, const void *data)
791 {
792    struct hk_descriptor_set tmp_set = {
793       .layout = layout,
794       .size = sizeof(push_set->data),
795       .mapped_ptr = push_set->data,
796    };
797    hk_descriptor_set_write_template(&tmp_set, template, data);
798 }
799