• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       if (vk_descriptor_type_is_dynamic(src_binding_layout->type)) {
320          const uint32_t dst_dyn_start =
321             dst_binding_layout->dynamic_buffer_index + copy->dstArrayElement;
322          const uint32_t src_dyn_start =
323             src_binding_layout->dynamic_buffer_index + copy->srcArrayElement;
324          typed_memcpy(&dst->dynamic_buffers[dst_dyn_start],
325                       &src->dynamic_buffers[src_dyn_start],
326                       copy->descriptorCount);
327       }
328    }
329 }
330 
331 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)332 hk_push_descriptor_set_update(struct hk_push_descriptor_set *push_set,
333                               struct hk_descriptor_set_layout *layout,
334                               uint32_t write_count,
335                               const VkWriteDescriptorSet *writes)
336 {
337    assert(layout->non_variable_descriptor_buffer_size < sizeof(push_set->data));
338    struct hk_descriptor_set set = {
339       .layout = layout,
340       .size = sizeof(push_set->data),
341       .mapped_ptr = push_set->data,
342    };
343 
344    for (uint32_t w = 0; w < write_count; w++) {
345       const VkWriteDescriptorSet *write = &writes[w];
346       assert(write->dstSet == VK_NULL_HANDLE);
347 
348       switch (write->descriptorType) {
349       case VK_DESCRIPTOR_TYPE_SAMPLER:
350       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
351       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
352       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
353          for (uint32_t j = 0; j < write->descriptorCount; j++) {
354             write_sampled_image_view_desc(
355                &set, write->pImageInfo + j, write->dstBinding,
356                write->dstArrayElement + j, write->descriptorType);
357          }
358          break;
359 
360       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
361          for (uint32_t j = 0; j < write->descriptorCount; j++) {
362             write_storage_image_view_desc(&set, write->pImageInfo + j,
363                                           write->dstBinding,
364                                           write->dstArrayElement + j);
365          }
366          break;
367 
368       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
369       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
370          for (uint32_t j = 0; j < write->descriptorCount; j++) {
371             write_buffer_view_desc(&set, write->pTexelBufferView[j],
372                                    write->dstBinding,
373                                    write->dstArrayElement + j);
374          }
375          break;
376 
377       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
378       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
379          for (uint32_t j = 0; j < write->descriptorCount; j++) {
380             write_buffer_desc(&set, write->pBufferInfo + j, write->dstBinding,
381                               write->dstArrayElement + j);
382          }
383          break;
384 
385       default:
386          break;
387       }
388    }
389 }
390 
391 static void hk_descriptor_pool_free(struct hk_descriptor_pool *pool,
392                                     uint64_t addr, uint64_t size);
393 
394 static void
hk_descriptor_set_destroy(struct hk_device * dev,struct hk_descriptor_pool * pool,struct hk_descriptor_set * set)395 hk_descriptor_set_destroy(struct hk_device *dev,
396                           struct hk_descriptor_pool *pool,
397                           struct hk_descriptor_set *set)
398 {
399    list_del(&set->link);
400    if (set->size > 0)
401       hk_descriptor_pool_free(pool, set->addr, set->size);
402    vk_descriptor_set_layout_unref(&dev->vk, &set->layout->vk);
403 
404    vk_object_free(&dev->vk, NULL, set);
405 }
406 
407 static void
hk_destroy_descriptor_pool(struct hk_device * dev,const VkAllocationCallbacks * pAllocator,struct hk_descriptor_pool * pool)408 hk_destroy_descriptor_pool(struct hk_device *dev,
409                            const VkAllocationCallbacks *pAllocator,
410                            struct hk_descriptor_pool *pool)
411 {
412    list_for_each_entry_safe(struct hk_descriptor_set, set, &pool->sets, link)
413       hk_descriptor_set_destroy(dev, pool, set);
414 
415    util_vma_heap_finish(&pool->heap);
416    agx_bo_unreference(&dev->dev, pool->bo);
417 
418    vk_object_free(&dev->vk, pAllocator, pool);
419 }
420 
421 VKAPI_ATTR VkResult VKAPI_CALL
hk_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)422 hk_CreateDescriptorPool(VkDevice _device,
423                         const VkDescriptorPoolCreateInfo *pCreateInfo,
424                         const VkAllocationCallbacks *pAllocator,
425                         VkDescriptorPool *pDescriptorPool)
426 {
427    VK_FROM_HANDLE(hk_device, dev, _device);
428    struct hk_physical_device *pdev = hk_device_physical(dev);
429    struct hk_descriptor_pool *pool;
430 
431    pool = vk_object_zalloc(&dev->vk, pAllocator, sizeof(*pool),
432                            VK_OBJECT_TYPE_DESCRIPTOR_POOL);
433    if (!pool)
434       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
435 
436    list_inithead(&pool->sets);
437 
438    const VkMutableDescriptorTypeCreateInfoEXT *mutable_info =
439       vk_find_struct_const(pCreateInfo->pNext,
440                            MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT);
441 
442    uint32_t max_align = 0;
443    for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
444       const VkMutableDescriptorTypeListEXT *type_list = NULL;
445       if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_EXT &&
446           mutable_info && i < mutable_info->mutableDescriptorTypeListCount)
447          type_list = &mutable_info->pMutableDescriptorTypeLists[i];
448 
449       uint32_t stride, alignment;
450       hk_descriptor_stride_align_for_type(pdev, pCreateInfo->pPoolSizes[i].type,
451                                           type_list, &stride, &alignment);
452       max_align = MAX2(max_align, alignment);
453    }
454 
455    uint64_t bo_size = 0;
456    for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
457       const VkMutableDescriptorTypeListEXT *type_list = NULL;
458       if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_EXT &&
459           mutable_info && i < mutable_info->mutableDescriptorTypeListCount)
460          type_list = &mutable_info->pMutableDescriptorTypeLists[i];
461 
462       uint32_t stride, alignment;
463       hk_descriptor_stride_align_for_type(pdev, pCreateInfo->pPoolSizes[i].type,
464                                           type_list, &stride, &alignment);
465       bo_size +=
466          MAX2(stride, max_align) * pCreateInfo->pPoolSizes[i].descriptorCount;
467    }
468 
469    /* Individual descriptor sets are aligned to the min UBO alignment to
470     * ensure that we don't end up with unaligned data access in any shaders.
471     * This means that each descriptor buffer allocated may burn up to 16B of
472     * extra space to get the right alignment.  (Technically, it's at most 28B
473     * because we're always going to start at least 4B aligned but we're being
474     * conservative here.)  Allocate enough extra space that we can chop it
475     * into maxSets pieces and align each one of them to 32B.
476     */
477    bo_size += HK_MIN_UBO_ALIGNMENT * pCreateInfo->maxSets;
478 
479    if (bo_size) {
480       pool->bo = agx_bo_create(&dev->dev, bo_size, 0, 0, "Descriptor pool");
481       if (!pool->bo) {
482          hk_destroy_descriptor_pool(dev, pAllocator, pool);
483          return vk_error(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY);
484       }
485 
486       pool->mapped_ptr = agx_bo_map(pool->bo);
487 
488       /* The BO may be larger thanks to GPU page alignment.  We may as well
489        * make that extra space available to the client.
490        */
491       assert(pool->bo->size >= bo_size);
492       util_vma_heap_init(&pool->heap, pool->bo->va->addr, pool->bo->size);
493    } else {
494       util_vma_heap_init(&pool->heap, 0, 0);
495    }
496 
497    *pDescriptorPool = hk_descriptor_pool_to_handle(pool);
498    return VK_SUCCESS;
499 }
500 
501 static VkResult
hk_descriptor_pool_alloc(struct hk_descriptor_pool * pool,uint64_t size,uint64_t alignment,uint64_t * addr_out,void ** map_out)502 hk_descriptor_pool_alloc(struct hk_descriptor_pool *pool, uint64_t size,
503                          uint64_t alignment, uint64_t *addr_out, void **map_out)
504 {
505    assert(size > 0);
506    uint64_t addr = util_vma_heap_alloc(&pool->heap, size, alignment);
507    if (addr == 0)
508       return VK_ERROR_OUT_OF_POOL_MEMORY;
509 
510    assert(addr >= pool->bo->va->addr);
511    assert(addr + size <= pool->bo->va->addr + pool->bo->size);
512    uint64_t offset = addr - pool->bo->va->addr;
513 
514    *addr_out = addr;
515    *map_out = pool->mapped_ptr + offset;
516 
517    return VK_SUCCESS;
518 }
519 
520 static void
hk_descriptor_pool_free(struct hk_descriptor_pool * pool,uint64_t addr,uint64_t size)521 hk_descriptor_pool_free(struct hk_descriptor_pool *pool, uint64_t addr,
522                         uint64_t size)
523 {
524    assert(size > 0);
525    assert(addr >= pool->bo->va->addr);
526    assert(addr + size <= pool->bo->va->addr + pool->bo->size);
527    util_vma_heap_free(&pool->heap, addr, size);
528 }
529 
530 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)531 hk_descriptor_set_create(struct hk_device *dev, struct hk_descriptor_pool *pool,
532                          struct hk_descriptor_set_layout *layout,
533                          uint32_t variable_count,
534                          struct hk_descriptor_set **out_set)
535 {
536    struct hk_descriptor_set *set;
537    VkResult result;
538 
539    uint32_t mem_size =
540       sizeof(struct hk_descriptor_set) +
541       layout->dynamic_buffer_count * sizeof(struct hk_buffer_address);
542 
543    set =
544       vk_object_zalloc(&dev->vk, NULL, mem_size, VK_OBJECT_TYPE_DESCRIPTOR_SET);
545    if (!set)
546       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
547 
548    set->size = layout->non_variable_descriptor_buffer_size;
549 
550    if (layout->binding_count > 0 &&
551        (layout->binding[layout->binding_count - 1].flags &
552         VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) {
553       uint32_t stride = layout->binding[layout->binding_count - 1].stride;
554 
555       /* Off by one so we don't underallocate the end. Otherwise vkd3d-proton
556        * descriptor-performance underallocates.
557        */
558       set->size += stride * (variable_count + 1);
559    }
560 
561    set->size = align64(set->size, HK_MIN_UBO_ALIGNMENT);
562 
563    if (set->size > 0) {
564       result = hk_descriptor_pool_alloc(pool, set->size, HK_MIN_UBO_ALIGNMENT,
565                                         &set->addr, &set->mapped_ptr);
566       if (result != VK_SUCCESS) {
567          vk_object_free(&dev->vk, NULL, set);
568          return result;
569       }
570    }
571 
572    vk_descriptor_set_layout_ref(&layout->vk);
573    set->layout = layout;
574 
575    for (uint32_t b = 0; b < layout->binding_count; b++) {
576       if (layout->binding[b].type != VK_DESCRIPTOR_TYPE_SAMPLER &&
577           layout->binding[b].type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
578          continue;
579 
580       if (layout->binding[b].immutable_samplers == NULL)
581          continue;
582 
583       uint32_t array_size = layout->binding[b].array_size;
584       if (layout->binding[b].flags &
585           VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)
586          array_size = variable_count;
587 
588       for (uint32_t j = 0; j < array_size; j++) {
589          write_sampled_image_view_desc(set, NULL, b, j,
590                                        layout->binding[b].type);
591       }
592    }
593 
594    list_addtail(&set->link, &pool->sets);
595    *out_set = set;
596 
597    return VK_SUCCESS;
598 }
599 
600 VKAPI_ATTR VkResult VKAPI_CALL
hk_AllocateDescriptorSets(VkDevice device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)601 hk_AllocateDescriptorSets(VkDevice device,
602                           const VkDescriptorSetAllocateInfo *pAllocateInfo,
603                           VkDescriptorSet *pDescriptorSets)
604 {
605    VK_FROM_HANDLE(hk_device, dev, device);
606    VK_FROM_HANDLE(hk_descriptor_pool, pool, pAllocateInfo->descriptorPool);
607 
608    VkResult result = VK_SUCCESS;
609    uint32_t i;
610 
611    struct hk_descriptor_set *set = NULL;
612 
613    const VkDescriptorSetVariableDescriptorCountAllocateInfo *var_desc_count =
614       vk_find_struct_const(
615          pAllocateInfo->pNext,
616          DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
617 
618    /* allocate a set of buffers for each shader to contain descriptors */
619    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
620       VK_FROM_HANDLE(hk_descriptor_set_layout, layout,
621                      pAllocateInfo->pSetLayouts[i]);
622       /* If descriptorSetCount is zero or this structure is not included in
623        * the pNext chain, then the variable lengths are considered to be zero.
624        */
625       const uint32_t variable_count =
626          var_desc_count && var_desc_count->descriptorSetCount > 0
627             ? var_desc_count->pDescriptorCounts[i]
628             : 0;
629 
630       result =
631          hk_descriptor_set_create(dev, pool, layout, variable_count, &set);
632       if (result != VK_SUCCESS)
633          break;
634 
635       pDescriptorSets[i] = hk_descriptor_set_to_handle(set);
636    }
637 
638    if (result != VK_SUCCESS) {
639       hk_FreeDescriptorSets(device, pAllocateInfo->descriptorPool, i,
640                             pDescriptorSets);
641       for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
642          pDescriptorSets[i] = VK_NULL_HANDLE;
643       }
644    }
645    return result;
646 }
647 
648 VKAPI_ATTR VkResult VKAPI_CALL
hk_FreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets)649 hk_FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
650                       uint32_t descriptorSetCount,
651                       const VkDescriptorSet *pDescriptorSets)
652 {
653    VK_FROM_HANDLE(hk_device, dev, device);
654    VK_FROM_HANDLE(hk_descriptor_pool, pool, descriptorPool);
655 
656    for (uint32_t i = 0; i < descriptorSetCount; i++) {
657       VK_FROM_HANDLE(hk_descriptor_set, set, pDescriptorSets[i]);
658 
659       if (set)
660          hk_descriptor_set_destroy(dev, pool, set);
661    }
662    return VK_SUCCESS;
663 }
664 
665 VKAPI_ATTR void VKAPI_CALL
hk_DestroyDescriptorPool(VkDevice device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)666 hk_DestroyDescriptorPool(VkDevice device, VkDescriptorPool _pool,
667                          const VkAllocationCallbacks *pAllocator)
668 {
669    VK_FROM_HANDLE(hk_device, dev, device);
670    VK_FROM_HANDLE(hk_descriptor_pool, pool, _pool);
671 
672    if (!_pool)
673       return;
674 
675    hk_destroy_descriptor_pool(dev, pAllocator, pool);
676 }
677 
678 VKAPI_ATTR VkResult VKAPI_CALL
hk_ResetDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)679 hk_ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
680                        VkDescriptorPoolResetFlags flags)
681 {
682    VK_FROM_HANDLE(hk_device, dev, device);
683    VK_FROM_HANDLE(hk_descriptor_pool, pool, descriptorPool);
684 
685    list_for_each_entry_safe(struct hk_descriptor_set, set, &pool->sets, link)
686       hk_descriptor_set_destroy(dev, pool, set);
687 
688    return VK_SUCCESS;
689 }
690 
691 static void
hk_descriptor_set_write_template(struct hk_descriptor_set * set,const struct vk_descriptor_update_template * template,const void * data)692 hk_descriptor_set_write_template(
693    struct hk_descriptor_set *set,
694    const struct vk_descriptor_update_template *template, const void *data)
695 {
696    for (uint32_t i = 0; i < template->entry_count; i++) {
697       const struct vk_descriptor_template_entry *entry = &template->entries[i];
698 
699       switch (entry->type) {
700       case VK_DESCRIPTOR_TYPE_SAMPLER:
701       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
702       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
703       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
704          for (uint32_t j = 0; j < entry->array_count; j++) {
705             const VkDescriptorImageInfo *info =
706                data + entry->offset + j * entry->stride;
707 
708             write_sampled_image_view_desc(set, info, entry->binding,
709                                           entry->array_element + j,
710                                           entry->type);
711          }
712          break;
713 
714       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
715          for (uint32_t j = 0; j < entry->array_count; j++) {
716             const VkDescriptorImageInfo *info =
717                data + entry->offset + j * entry->stride;
718 
719             write_storage_image_view_desc(set, info, entry->binding,
720                                           entry->array_element + j);
721          }
722          break;
723 
724       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
725       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
726          for (uint32_t j = 0; j < entry->array_count; j++) {
727             const VkBufferView *bview =
728                data + entry->offset + j * entry->stride;
729 
730             write_buffer_view_desc(set, *bview, entry->binding,
731                                    entry->array_element + j);
732          }
733          break;
734 
735       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
736       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
737          for (uint32_t j = 0; j < entry->array_count; j++) {
738             const VkDescriptorBufferInfo *info =
739                data + entry->offset + j * entry->stride;
740 
741             write_buffer_desc(set, info, entry->binding,
742                               entry->array_element + j);
743          }
744          break;
745 
746       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
747       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
748          for (uint32_t j = 0; j < entry->array_count; j++) {
749             const VkDescriptorBufferInfo *info =
750                data + entry->offset + j * entry->stride;
751 
752             write_dynamic_buffer_desc(set, info, entry->binding,
753                                       entry->array_element + j);
754          }
755          break;
756 
757       case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
758          write_desc(set, entry->binding, entry->array_element,
759                     data + entry->offset, entry->array_count);
760          break;
761 
762       default:
763          break;
764       }
765    }
766 }
767 
768 VKAPI_ATTR void VKAPI_CALL
hk_UpdateDescriptorSetWithTemplate(VkDevice device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)769 hk_UpdateDescriptorSetWithTemplate(
770    VkDevice device, VkDescriptorSet descriptorSet,
771    VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void *pData)
772 {
773    VK_FROM_HANDLE(hk_descriptor_set, set, descriptorSet);
774    VK_FROM_HANDLE(vk_descriptor_update_template, template,
775                   descriptorUpdateTemplate);
776 
777    hk_descriptor_set_write_template(set, template, pData);
778 }
779 
780 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)781 hk_push_descriptor_set_update_template(
782    struct hk_push_descriptor_set *push_set,
783    struct hk_descriptor_set_layout *layout,
784    const struct vk_descriptor_update_template *template, const void *data)
785 {
786    struct hk_descriptor_set tmp_set = {
787       .layout = layout,
788       .size = sizeof(push_set->data),
789       .mapped_ptr = push_set->data,
790    };
791    hk_descriptor_set_write_template(&tmp_set, template, data);
792 }
793