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