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