1/* 2 * Copyright 2019 Google LLC 3 * SPDX-License-Identifier: MIT 4 * 5 * based in part on anv and radv which are: 6 * Copyright © 2015 Intel Corporation 7 * Copyright © 2016 Red Hat. 8 * Copyright © 2016 Bas Nieuwenhuizen 9 */ 10 11#include "vn_descriptor_set.h" 12 13#include "venus-protocol/vn_protocol_driver_descriptor_pool.h" 14#include "venus-protocol/vn_protocol_driver_descriptor_set.h" 15#include "venus-protocol/vn_protocol_driver_descriptor_set_layout.h" 16#include "venus-protocol/vn_protocol_driver_descriptor_update_template.h" 17 18#include "vn_device.h" 19 20static void 21vn_descriptor_set_layout_destroy(struct vn_device *dev, 22 struct vn_descriptor_set_layout *layout) 23{ 24 VkDevice dev_handle = vn_device_to_handle(dev); 25 VkDescriptorSetLayout layout_handle = 26 vn_descriptor_set_layout_to_handle(layout); 27 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 28 29 vn_async_vkDestroyDescriptorSetLayout(dev->instance, dev_handle, 30 layout_handle, NULL); 31 32 vn_object_base_fini(&layout->base); 33 vk_free(alloc, layout); 34} 35 36static inline struct vn_descriptor_set_layout * 37vn_descriptor_set_layout_ref(struct vn_device *dev, 38 struct vn_descriptor_set_layout *layout) 39{ 40 vn_refcount_inc(&layout->refcount); 41 return layout; 42} 43 44static inline void 45vn_descriptor_set_layout_unref(struct vn_device *dev, 46 struct vn_descriptor_set_layout *layout) 47{ 48 if (vn_refcount_dec(&layout->refcount)) 49 vn_descriptor_set_layout_destroy(dev, layout); 50} 51 52static void 53vn_descriptor_set_destroy(struct vn_device *dev, 54 struct vn_descriptor_set *set, 55 const VkAllocationCallbacks *alloc) 56{ 57 list_del(&set->head); 58 59 vn_descriptor_set_layout_unref(dev, set->layout); 60 61 vn_object_base_fini(&set->base); 62 vk_free(alloc, set); 63} 64 65/* Mapping VkDescriptorType to array index */ 66static enum vn_descriptor_type 67vn_descriptor_type_index(VkDescriptorType type) 68{ 69 switch (type) { 70 case VK_DESCRIPTOR_TYPE_SAMPLER: 71 return VN_DESCRIPTOR_TYPE_SAMPLER; 72 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 73 return VN_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 74 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 75 return VN_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 76 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 77 return VN_DESCRIPTOR_TYPE_STORAGE_IMAGE; 78 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 79 return VN_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 80 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 81 return VN_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 82 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 83 return VN_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 84 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 85 return VN_DESCRIPTOR_TYPE_STORAGE_BUFFER; 86 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 87 return VN_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 88 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 89 return VN_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 90 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 91 return VN_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 92 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 93 return VN_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; 94 default: 95 break; 96 } 97 98 unreachable("bad VkDescriptorType"); 99} 100 101/* descriptor set layout commands */ 102 103void 104vn_GetDescriptorSetLayoutSupport( 105 VkDevice device, 106 const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 107 VkDescriptorSetLayoutSupport *pSupport) 108{ 109 struct vn_device *dev = vn_device_from_handle(device); 110 111 /* TODO per-device cache */ 112 vn_call_vkGetDescriptorSetLayoutSupport(dev->instance, device, pCreateInfo, 113 pSupport); 114} 115 116static void 117vn_descriptor_set_layout_init( 118 struct vn_device *dev, 119 const VkDescriptorSetLayoutCreateInfo *create_info, 120 uint32_t last_binding, 121 struct vn_descriptor_set_layout *layout) 122{ 123 VkDevice dev_handle = vn_device_to_handle(dev); 124 VkDescriptorSetLayout layout_handle = 125 vn_descriptor_set_layout_to_handle(layout); 126 const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags = 127 vk_find_struct_const(create_info->pNext, 128 DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO); 129 130 /* 14.2.1. Descriptor Set Layout 131 * 132 * If bindingCount is zero or if this structure is not included in 133 * the pNext chain, the VkDescriptorBindingFlags for each descriptor 134 * set layout binding is considered to be zero. 135 */ 136 if (binding_flags && !binding_flags->bindingCount) 137 binding_flags = NULL; 138 139 layout->refcount = VN_REFCOUNT_INIT(1); 140 layout->last_binding = last_binding; 141 142 for (uint32_t i = 0; i < create_info->bindingCount; i++) { 143 const VkDescriptorSetLayoutBinding *binding_info = 144 &create_info->pBindings[i]; 145 struct vn_descriptor_set_layout_binding *binding = 146 &layout->bindings[binding_info->binding]; 147 148 if (binding_info->binding == last_binding) { 149 /* 14.2.1. Descriptor Set Layout 150 * 151 * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must only be 152 * used for the last binding in the descriptor set layout (i.e. the 153 * binding with the largest value of binding). 154 * 155 * 41. Features 156 * 157 * descriptorBindingVariableDescriptorCount indicates whether the 158 * implementation supports descriptor sets with a variable-sized last 159 * binding. If this feature is not enabled, 160 * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must not be 161 * used. 162 */ 163 layout->has_variable_descriptor_count = 164 binding_flags && 165 (binding_flags->pBindingFlags[i] & 166 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT); 167 } 168 169 binding->type = binding_info->descriptorType; 170 binding->count = binding_info->descriptorCount; 171 172 switch (binding_info->descriptorType) { 173 case VK_DESCRIPTOR_TYPE_SAMPLER: 174 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 175 binding->has_immutable_samplers = binding_info->pImmutableSamplers; 176 break; 177 default: 178 break; 179 } 180 } 181 182 vn_async_vkCreateDescriptorSetLayout(dev->instance, dev_handle, 183 create_info, NULL, &layout_handle); 184} 185 186VkResult 187vn_CreateDescriptorSetLayout( 188 VkDevice device, 189 const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 190 const VkAllocationCallbacks *pAllocator, 191 VkDescriptorSetLayout *pSetLayout) 192{ 193 struct vn_device *dev = vn_device_from_handle(device); 194 /* ignore pAllocator as the layout is reference-counted */ 195 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 196 197 uint32_t last_binding = 0; 198 VkDescriptorSetLayoutBinding *local_bindings = NULL; 199 VkDescriptorSetLayoutCreateInfo local_create_info; 200 if (pCreateInfo->bindingCount) { 201 /* the encoder does not ignore 202 * VkDescriptorSetLayoutBinding::pImmutableSamplers when it should 203 */ 204 const size_t binding_size = 205 sizeof(*pCreateInfo->pBindings) * pCreateInfo->bindingCount; 206 local_bindings = vk_alloc(alloc, binding_size, VN_DEFAULT_ALIGN, 207 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 208 if (!local_bindings) 209 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 210 211 memcpy(local_bindings, pCreateInfo->pBindings, binding_size); 212 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { 213 VkDescriptorSetLayoutBinding *binding = &local_bindings[i]; 214 215 if (last_binding < binding->binding) 216 last_binding = binding->binding; 217 218 switch (binding->descriptorType) { 219 case VK_DESCRIPTOR_TYPE_SAMPLER: 220 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 221 break; 222 default: 223 binding->pImmutableSamplers = NULL; 224 break; 225 } 226 } 227 228 local_create_info = *pCreateInfo; 229 local_create_info.pBindings = local_bindings; 230 pCreateInfo = &local_create_info; 231 } 232 233 const size_t layout_size = 234 offsetof(struct vn_descriptor_set_layout, bindings[last_binding + 1]); 235 /* allocated with the device scope */ 236 struct vn_descriptor_set_layout *layout = 237 vk_zalloc(alloc, layout_size, VN_DEFAULT_ALIGN, 238 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 239 if (!layout) { 240 vk_free(alloc, local_bindings); 241 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 242 } 243 244 vn_object_base_init(&layout->base, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, 245 &dev->base); 246 247 vn_descriptor_set_layout_init(dev, pCreateInfo, last_binding, layout); 248 249 vk_free(alloc, local_bindings); 250 251 *pSetLayout = vn_descriptor_set_layout_to_handle(layout); 252 253 return VK_SUCCESS; 254} 255 256void 257vn_DestroyDescriptorSetLayout(VkDevice device, 258 VkDescriptorSetLayout descriptorSetLayout, 259 const VkAllocationCallbacks *pAllocator) 260{ 261 struct vn_device *dev = vn_device_from_handle(device); 262 struct vn_descriptor_set_layout *layout = 263 vn_descriptor_set_layout_from_handle(descriptorSetLayout); 264 265 if (!layout) 266 return; 267 268 vn_descriptor_set_layout_unref(dev, layout); 269} 270 271/* descriptor pool commands */ 272 273VkResult 274vn_CreateDescriptorPool(VkDevice device, 275 const VkDescriptorPoolCreateInfo *pCreateInfo, 276 const VkAllocationCallbacks *pAllocator, 277 VkDescriptorPool *pDescriptorPool) 278{ 279 VN_TRACE_FUNC(); 280 struct vn_device *dev = vn_device_from_handle(device); 281 const VkAllocationCallbacks *alloc = 282 pAllocator ? pAllocator : &dev->base.base.alloc; 283 284 const VkDescriptorPoolInlineUniformBlockCreateInfo *iub_info = 285 vk_find_struct_const(pCreateInfo->pNext, 286 DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO); 287 288 struct vn_descriptor_pool *pool = 289 vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN, 290 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 291 if (!pool) 292 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 293 294 vn_object_base_init(&pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL, 295 &dev->base); 296 297 pool->allocator = *alloc; 298 299 /* Without VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, the set 300 * allocation must not fail due to a fragmented pool per spec. In this 301 * case, set allocation can be asynchronous with pool resource tracking. 302 */ 303 pool->async_set_allocation = 304 !VN_PERF(NO_ASYNC_SET_ALLOC) && 305 !(pCreateInfo->flags & 306 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT); 307 308 pool->max.set_count = pCreateInfo->maxSets; 309 310 if (iub_info) 311 pool->max.iub_binding_count = iub_info->maxInlineUniformBlockBindings; 312 313 for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; i++) { 314 const VkDescriptorPoolSize *pool_size = &pCreateInfo->pPoolSizes[i]; 315 const uint32_t type_index = vn_descriptor_type_index(pool_size->type); 316 317 assert(type_index < VN_NUM_DESCRIPTOR_TYPES); 318 319 pool->max.descriptor_counts[type_index] += pool_size->descriptorCount; 320 321 assert((pCreateInfo->pPoolSizes[i].type != 322 VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) || 323 iub_info); 324 } 325 326 list_inithead(&pool->descriptor_sets); 327 328 VkDescriptorPool pool_handle = vn_descriptor_pool_to_handle(pool); 329 vn_async_vkCreateDescriptorPool(dev->instance, device, pCreateInfo, NULL, 330 &pool_handle); 331 332 *pDescriptorPool = pool_handle; 333 334 return VK_SUCCESS; 335} 336 337void 338vn_DestroyDescriptorPool(VkDevice device, 339 VkDescriptorPool descriptorPool, 340 const VkAllocationCallbacks *pAllocator) 341{ 342 VN_TRACE_FUNC(); 343 struct vn_device *dev = vn_device_from_handle(device); 344 struct vn_descriptor_pool *pool = 345 vn_descriptor_pool_from_handle(descriptorPool); 346 const VkAllocationCallbacks *alloc; 347 348 if (!pool) 349 return; 350 351 alloc = pAllocator ? pAllocator : &pool->allocator; 352 353 /* We must emit vkDestroyDescriptorPool before freeing the sets in 354 * pool->descriptor_sets. Otherwise, another thread might reuse their 355 * object ids while they still refer to the sets in the renderer. 356 */ 357 vn_async_vkDestroyDescriptorPool(dev->instance, device, descriptorPool, 358 NULL); 359 360 list_for_each_entry_safe(struct vn_descriptor_set, set, 361 &pool->descriptor_sets, head) 362 vn_descriptor_set_destroy(dev, set, alloc); 363 364 vn_object_base_fini(&pool->base); 365 vk_free(alloc, pool); 366} 367 368static bool 369vn_descriptor_pool_alloc_descriptors( 370 struct vn_descriptor_pool *pool, 371 const struct vn_descriptor_set_layout *layout, 372 uint32_t last_binding_descriptor_count) 373{ 374 struct vn_descriptor_pool_state recovery; 375 376 if (!pool->async_set_allocation) 377 return true; 378 379 if (pool->used.set_count == pool->max.set_count) 380 return false; 381 382 /* backup current pool state to recovery */ 383 recovery = pool->used; 384 385 ++pool->used.set_count; 386 387 for (uint32_t i = 0; i <= layout->last_binding; i++) { 388 const VkDescriptorType type = layout->bindings[i].type; 389 const uint32_t count = i == layout->last_binding 390 ? last_binding_descriptor_count 391 : layout->bindings[i].count; 392 393 /* Allocation may fail if a call to vkAllocateDescriptorSets would cause 394 * the total number of inline uniform block bindings allocated from the 395 * pool to exceed the value of 396 * VkDescriptorPoolInlineUniformBlockCreateInfo::maxInlineUniformBlockBindings 397 * used to create the descriptor pool. 398 */ 399 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { 400 if (++pool->used.iub_binding_count > pool->max.iub_binding_count) { 401 /* restore pool state before this allocation */ 402 pool->used = recovery; 403 return false; 404 } 405 } 406 407 const uint32_t type_index = vn_descriptor_type_index(type); 408 pool->used.descriptor_counts[type_index] += count; 409 410 if (pool->used.descriptor_counts[type_index] > 411 pool->max.descriptor_counts[type_index]) { 412 /* restore pool state before this allocation */ 413 pool->used = recovery; 414 return false; 415 } 416 } 417 418 return true; 419} 420 421static void 422vn_descriptor_pool_free_descriptors( 423 struct vn_descriptor_pool *pool, 424 const struct vn_descriptor_set_layout *layout, 425 uint32_t last_binding_descriptor_count) 426{ 427 if (!pool->async_set_allocation) 428 return; 429 430 for (uint32_t i = 0; i <= layout->last_binding; i++) { 431 const uint32_t count = i == layout->last_binding 432 ? last_binding_descriptor_count 433 : layout->bindings[i].count; 434 435 pool->used.descriptor_counts[vn_descriptor_type_index( 436 layout->bindings[i].type)] -= count; 437 438 if (layout->bindings[i].type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) 439 --pool->used.iub_binding_count; 440 } 441 442 --pool->used.set_count; 443} 444 445static void 446vn_descriptor_pool_reset_descriptors(struct vn_descriptor_pool *pool) 447{ 448 if (!pool->async_set_allocation) 449 return; 450 451 memset(&pool->used, 0, sizeof(pool->used)); 452} 453 454VkResult 455vn_ResetDescriptorPool(VkDevice device, 456 VkDescriptorPool descriptorPool, 457 VkDescriptorPoolResetFlags flags) 458{ 459 VN_TRACE_FUNC(); 460 struct vn_device *dev = vn_device_from_handle(device); 461 struct vn_descriptor_pool *pool = 462 vn_descriptor_pool_from_handle(descriptorPool); 463 const VkAllocationCallbacks *alloc = &pool->allocator; 464 465 vn_async_vkResetDescriptorPool(dev->instance, device, descriptorPool, 466 flags); 467 468 list_for_each_entry_safe(struct vn_descriptor_set, set, 469 &pool->descriptor_sets, head) 470 vn_descriptor_set_destroy(dev, set, alloc); 471 472 vn_descriptor_pool_reset_descriptors(pool); 473 474 return VK_SUCCESS; 475} 476 477/* descriptor set commands */ 478 479VkResult 480vn_AllocateDescriptorSets(VkDevice device, 481 const VkDescriptorSetAllocateInfo *pAllocateInfo, 482 VkDescriptorSet *pDescriptorSets) 483{ 484 VN_TRACE_FUNC(); 485 struct vn_device *dev = vn_device_from_handle(device); 486 struct vn_descriptor_pool *pool = 487 vn_descriptor_pool_from_handle(pAllocateInfo->descriptorPool); 488 const VkAllocationCallbacks *alloc = &pool->allocator; 489 const VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_info = 490 NULL; 491 VkResult result; 492 493 /* 14.2.3. Allocation of Descriptor Sets 494 * 495 * If descriptorSetCount is zero or this structure is not included in 496 * the pNext chain, then the variable lengths are considered to be zero. 497 */ 498 variable_info = vk_find_struct_const( 499 pAllocateInfo->pNext, 500 DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO); 501 502 if (variable_info && !variable_info->descriptorSetCount) 503 variable_info = NULL; 504 505 for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 506 struct vn_descriptor_set_layout *layout = 507 vn_descriptor_set_layout_from_handle(pAllocateInfo->pSetLayouts[i]); 508 uint32_t last_binding_descriptor_count = 0; 509 struct vn_descriptor_set *set = NULL; 510 511 /* 14.2.3. Allocation of Descriptor Sets 512 * 513 * If VkDescriptorSetAllocateInfo::pSetLayouts[i] does not include a 514 * variable count descriptor binding, then pDescriptorCounts[i] is 515 * ignored. 516 */ 517 if (!layout->has_variable_descriptor_count) { 518 last_binding_descriptor_count = 519 layout->bindings[layout->last_binding].count; 520 } else if (variable_info) { 521 last_binding_descriptor_count = variable_info->pDescriptorCounts[i]; 522 } 523 524 if (!vn_descriptor_pool_alloc_descriptors( 525 pool, layout, last_binding_descriptor_count)) { 526 pDescriptorSets[i] = VK_NULL_HANDLE; 527 result = VK_ERROR_OUT_OF_POOL_MEMORY; 528 goto fail; 529 } 530 531 set = vk_zalloc(alloc, sizeof(*set), VN_DEFAULT_ALIGN, 532 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 533 if (!set) { 534 vn_descriptor_pool_free_descriptors(pool, layout, 535 last_binding_descriptor_count); 536 pDescriptorSets[i] = VK_NULL_HANDLE; 537 result = VK_ERROR_OUT_OF_HOST_MEMORY; 538 goto fail; 539 } 540 541 vn_object_base_init(&set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET, 542 &dev->base); 543 544 /* We might reorder vkCmdBindDescriptorSets after 545 * vkDestroyDescriptorSetLayout due to batching. The spec says 546 * 547 * VkDescriptorSetLayout objects may be accessed by commands that 548 * operate on descriptor sets allocated using that layout, and those 549 * descriptor sets must not be updated with vkUpdateDescriptorSets 550 * after the descriptor set layout has been destroyed. Otherwise, a 551 * VkDescriptorSetLayout object passed as a parameter to create 552 * another object is not further accessed by that object after the 553 * duration of the command it is passed into. 554 * 555 * It is ambiguous but the reordering is likely invalid. Let's keep the 556 * layout alive with the set to defer vkDestroyDescriptorSetLayout. 557 */ 558 set->layout = vn_descriptor_set_layout_ref(dev, layout); 559 set->last_binding_descriptor_count = last_binding_descriptor_count; 560 list_addtail(&set->head, &pool->descriptor_sets); 561 562 VkDescriptorSet set_handle = vn_descriptor_set_to_handle(set); 563 pDescriptorSets[i] = set_handle; 564 } 565 566 if (pool->async_set_allocation) { 567 vn_async_vkAllocateDescriptorSets(dev->instance, device, pAllocateInfo, 568 pDescriptorSets); 569 } else { 570 result = vn_call_vkAllocateDescriptorSets( 571 dev->instance, device, pAllocateInfo, pDescriptorSets); 572 if (result != VK_SUCCESS) 573 goto fail; 574 } 575 576 return VK_SUCCESS; 577 578fail: 579 for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 580 struct vn_descriptor_set *set = 581 vn_descriptor_set_from_handle(pDescriptorSets[i]); 582 if (!set) 583 break; 584 585 vn_descriptor_pool_free_descriptors(pool, set->layout, 586 set->last_binding_descriptor_count); 587 588 vn_descriptor_set_destroy(dev, set, alloc); 589 } 590 591 memset(pDescriptorSets, 0, 592 sizeof(*pDescriptorSets) * pAllocateInfo->descriptorSetCount); 593 594 return vn_error(dev->instance, result); 595} 596 597VkResult 598vn_FreeDescriptorSets(VkDevice device, 599 VkDescriptorPool descriptorPool, 600 uint32_t descriptorSetCount, 601 const VkDescriptorSet *pDescriptorSets) 602{ 603 VN_TRACE_FUNC(); 604 struct vn_device *dev = vn_device_from_handle(device); 605 struct vn_descriptor_pool *pool = 606 vn_descriptor_pool_from_handle(descriptorPool); 607 const VkAllocationCallbacks *alloc = &pool->allocator; 608 609 vn_async_vkFreeDescriptorSets(dev->instance, device, descriptorPool, 610 descriptorSetCount, pDescriptorSets); 611 612 for (uint32_t i = 0; i < descriptorSetCount; i++) { 613 struct vn_descriptor_set *set = 614 vn_descriptor_set_from_handle(pDescriptorSets[i]); 615 616 if (!set) 617 continue; 618 619 vn_descriptor_set_destroy(dev, set, alloc); 620 } 621 622 return VK_SUCCESS; 623} 624 625static struct vn_update_descriptor_sets * 626vn_update_descriptor_sets_alloc(uint32_t write_count, 627 uint32_t image_count, 628 uint32_t buffer_count, 629 uint32_t view_count, 630 uint32_t iub_count, 631 const VkAllocationCallbacks *alloc, 632 VkSystemAllocationScope scope) 633{ 634 const size_t writes_offset = sizeof(struct vn_update_descriptor_sets); 635 const size_t images_offset = 636 writes_offset + sizeof(VkWriteDescriptorSet) * write_count; 637 const size_t buffers_offset = 638 images_offset + sizeof(VkDescriptorImageInfo) * image_count; 639 const size_t views_offset = 640 buffers_offset + sizeof(VkDescriptorBufferInfo) * buffer_count; 641 const size_t iubs_offset = 642 views_offset + sizeof(VkBufferView) * view_count; 643 const size_t alloc_size = 644 iubs_offset + 645 sizeof(VkWriteDescriptorSetInlineUniformBlock) * iub_count; 646 647 void *storage = vk_alloc(alloc, alloc_size, VN_DEFAULT_ALIGN, scope); 648 if (!storage) 649 return NULL; 650 651 struct vn_update_descriptor_sets *update = storage; 652 update->write_count = write_count; 653 update->writes = storage + writes_offset; 654 update->images = storage + images_offset; 655 update->buffers = storage + buffers_offset; 656 update->views = storage + views_offset; 657 update->iubs = storage + iubs_offset; 658 659 return update; 660} 661 662static struct vn_update_descriptor_sets * 663vn_update_descriptor_sets_parse_writes(uint32_t write_count, 664 const VkWriteDescriptorSet *writes, 665 const VkAllocationCallbacks *alloc) 666{ 667 uint32_t img_count = 0; 668 for (uint32_t i = 0; i < write_count; i++) { 669 const VkWriteDescriptorSet *write = &writes[i]; 670 switch (write->descriptorType) { 671 case VK_DESCRIPTOR_TYPE_SAMPLER: 672 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 673 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 674 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 675 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 676 img_count += write->descriptorCount; 677 break; 678 default: 679 break; 680 } 681 } 682 683 struct vn_update_descriptor_sets *update = 684 vn_update_descriptor_sets_alloc(write_count, img_count, 0, 0, 0, alloc, 685 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 686 if (!update) 687 return NULL; 688 689 /* the encoder does not ignore 690 * VkWriteDescriptorSet::{pImageInfo,pBufferInfo,pTexelBufferView} when it 691 * should 692 * 693 * TODO make the encoder smarter 694 */ 695 memcpy(update->writes, writes, sizeof(*writes) * write_count); 696 img_count = 0; 697 for (uint32_t i = 0; i < write_count; i++) { 698 const struct vn_descriptor_set *set = 699 vn_descriptor_set_from_handle(writes[i].dstSet); 700 const struct vn_descriptor_set_layout_binding *binding = 701 &set->layout->bindings[writes[i].dstBinding]; 702 VkWriteDescriptorSet *write = &update->writes[i]; 703 VkDescriptorImageInfo *imgs = &update->images[img_count]; 704 705 switch (write->descriptorType) { 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_STORAGE_IMAGE: 710 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 711 memcpy(imgs, write->pImageInfo, 712 sizeof(*imgs) * write->descriptorCount); 713 img_count += write->descriptorCount; 714 715 for (uint32_t j = 0; j < write->descriptorCount; j++) { 716 switch (write->descriptorType) { 717 case VK_DESCRIPTOR_TYPE_SAMPLER: 718 imgs[j].imageView = VK_NULL_HANDLE; 719 break; 720 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 721 if (binding->has_immutable_samplers) 722 imgs[j].sampler = VK_NULL_HANDLE; 723 break; 724 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 725 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 726 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 727 imgs[j].sampler = VK_NULL_HANDLE; 728 break; 729 default: 730 break; 731 } 732 } 733 734 write->pImageInfo = imgs; 735 write->pBufferInfo = NULL; 736 write->pTexelBufferView = NULL; 737 break; 738 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 739 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 740 write->pImageInfo = NULL; 741 write->pBufferInfo = NULL; 742 break; 743 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 744 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 745 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 746 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 747 write->pImageInfo = NULL; 748 write->pTexelBufferView = NULL; 749 break; 750 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 751 default: 752 write->pImageInfo = NULL; 753 write->pBufferInfo = NULL; 754 write->pTexelBufferView = NULL; 755 break; 756 } 757 } 758 759 return update; 760} 761 762void 763vn_UpdateDescriptorSets(VkDevice device, 764 uint32_t descriptorWriteCount, 765 const VkWriteDescriptorSet *pDescriptorWrites, 766 uint32_t descriptorCopyCount, 767 const VkCopyDescriptorSet *pDescriptorCopies) 768{ 769 VN_TRACE_FUNC(); 770 struct vn_device *dev = vn_device_from_handle(device); 771 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 772 773 struct vn_update_descriptor_sets *update = 774 vn_update_descriptor_sets_parse_writes(descriptorWriteCount, 775 pDescriptorWrites, alloc); 776 if (!update) { 777 /* TODO update one-by-one? */ 778 vn_log(dev->instance, "TODO descriptor set update ignored due to OOM"); 779 return; 780 } 781 782 vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count, 783 update->writes, descriptorCopyCount, 784 pDescriptorCopies); 785 786 vk_free(alloc, update); 787} 788 789/* descriptor update template commands */ 790 791static struct vn_update_descriptor_sets * 792vn_update_descriptor_sets_parse_template( 793 const VkDescriptorUpdateTemplateCreateInfo *create_info, 794 const VkAllocationCallbacks *alloc, 795 struct vn_descriptor_update_template_entry *entries) 796{ 797 uint32_t img_count = 0; 798 uint32_t buf_count = 0; 799 uint32_t view_count = 0; 800 uint32_t iub_count = 0; 801 for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) { 802 const VkDescriptorUpdateTemplateEntry *entry = 803 &create_info->pDescriptorUpdateEntries[i]; 804 805 switch (entry->descriptorType) { 806 case VK_DESCRIPTOR_TYPE_SAMPLER: 807 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 808 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 809 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 810 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 811 img_count += entry->descriptorCount; 812 break; 813 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 814 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 815 view_count += entry->descriptorCount; 816 break; 817 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 818 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 819 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 820 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 821 buf_count += entry->descriptorCount; 822 break; 823 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 824 iub_count += 1; 825 break; 826 default: 827 unreachable("unhandled descriptor type"); 828 break; 829 } 830 } 831 832 struct vn_update_descriptor_sets *update = vn_update_descriptor_sets_alloc( 833 create_info->descriptorUpdateEntryCount, img_count, buf_count, 834 view_count, iub_count, alloc, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 835 if (!update) 836 return NULL; 837 838 img_count = 0; 839 buf_count = 0; 840 view_count = 0; 841 iub_count = 0; 842 for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) { 843 const VkDescriptorUpdateTemplateEntry *entry = 844 &create_info->pDescriptorUpdateEntries[i]; 845 VkWriteDescriptorSet *write = &update->writes[i]; 846 847 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 848 write->pNext = NULL; 849 write->dstBinding = entry->dstBinding; 850 write->dstArrayElement = entry->dstArrayElement; 851 write->descriptorCount = entry->descriptorCount; 852 write->descriptorType = entry->descriptorType; 853 854 entries[i].offset = entry->offset; 855 entries[i].stride = entry->stride; 856 857 switch (entry->descriptorType) { 858 case VK_DESCRIPTOR_TYPE_SAMPLER: 859 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 860 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 861 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 862 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 863 write->pImageInfo = &update->images[img_count]; 864 write->pBufferInfo = NULL; 865 write->pTexelBufferView = NULL; 866 img_count += entry->descriptorCount; 867 break; 868 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 869 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 870 write->pImageInfo = NULL; 871 write->pBufferInfo = NULL; 872 write->pTexelBufferView = &update->views[view_count]; 873 view_count += entry->descriptorCount; 874 break; 875 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 876 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 877 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 878 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 879 write->pImageInfo = NULL; 880 write->pBufferInfo = &update->buffers[buf_count]; 881 write->pTexelBufferView = NULL; 882 buf_count += entry->descriptorCount; 883 break; 884 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 885 write->pImageInfo = NULL; 886 write->pBufferInfo = NULL; 887 write->pTexelBufferView = NULL; 888 VkWriteDescriptorSetInlineUniformBlock *iub_data = 889 &update->iubs[iub_count]; 890 iub_data->sType = 891 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK; 892 iub_data->pNext = write->pNext; 893 iub_data->dataSize = entry->descriptorCount; 894 write->pNext = iub_data; 895 iub_count += 1; 896 break; 897 default: 898 break; 899 } 900 } 901 902 return update; 903} 904 905VkResult 906vn_CreateDescriptorUpdateTemplate( 907 VkDevice device, 908 const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo, 909 const VkAllocationCallbacks *pAllocator, 910 VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) 911{ 912 VN_TRACE_FUNC(); 913 struct vn_device *dev = vn_device_from_handle(device); 914 const VkAllocationCallbacks *alloc = 915 pAllocator ? pAllocator : &dev->base.base.alloc; 916 917 const size_t templ_size = 918 offsetof(struct vn_descriptor_update_template, 919 entries[pCreateInfo->descriptorUpdateEntryCount + 1]); 920 struct vn_descriptor_update_template *templ = vk_zalloc( 921 alloc, templ_size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 922 if (!templ) 923 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 924 925 vn_object_base_init(&templ->base, 926 VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, &dev->base); 927 928 templ->update = vn_update_descriptor_sets_parse_template( 929 pCreateInfo, alloc, templ->entries); 930 if (!templ->update) { 931 vk_free(alloc, templ); 932 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 933 } 934 935 mtx_init(&templ->mutex, mtx_plain); 936 937 /* no host object */ 938 VkDescriptorUpdateTemplate templ_handle = 939 vn_descriptor_update_template_to_handle(templ); 940 *pDescriptorUpdateTemplate = templ_handle; 941 942 return VK_SUCCESS; 943} 944 945void 946vn_DestroyDescriptorUpdateTemplate( 947 VkDevice device, 948 VkDescriptorUpdateTemplate descriptorUpdateTemplate, 949 const VkAllocationCallbacks *pAllocator) 950{ 951 VN_TRACE_FUNC(); 952 struct vn_device *dev = vn_device_from_handle(device); 953 struct vn_descriptor_update_template *templ = 954 vn_descriptor_update_template_from_handle(descriptorUpdateTemplate); 955 const VkAllocationCallbacks *alloc = 956 pAllocator ? pAllocator : &dev->base.base.alloc; 957 958 if (!templ) 959 return; 960 961 /* no host object */ 962 vk_free(alloc, templ->update); 963 mtx_destroy(&templ->mutex); 964 965 vn_object_base_fini(&templ->base); 966 vk_free(alloc, templ); 967} 968 969void 970vn_UpdateDescriptorSetWithTemplate( 971 VkDevice device, 972 VkDescriptorSet descriptorSet, 973 VkDescriptorUpdateTemplate descriptorUpdateTemplate, 974 const void *pData) 975{ 976 VN_TRACE_FUNC(); 977 struct vn_device *dev = vn_device_from_handle(device); 978 struct vn_descriptor_set *set = 979 vn_descriptor_set_from_handle(descriptorSet); 980 struct vn_descriptor_update_template *templ = 981 vn_descriptor_update_template_from_handle(descriptorUpdateTemplate); 982 struct vn_update_descriptor_sets *update = templ->update; 983 984 /* duplicate update instead to avoid locking? */ 985 mtx_lock(&templ->mutex); 986 987 for (uint32_t i = 0; i < update->write_count; i++) { 988 const struct vn_descriptor_update_template_entry *entry = 989 &templ->entries[i]; 990 const struct vn_descriptor_set_layout_binding *binding = 991 &set->layout->bindings[update->writes[i].dstBinding]; 992 VkWriteDescriptorSet *write = &update->writes[i]; 993 994 write->dstSet = vn_descriptor_set_to_handle(set); 995 996 switch (write->descriptorType) { 997 case VK_DESCRIPTOR_TYPE_SAMPLER: 998 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 999 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1000 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1001 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1002 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1003 const bool need_sampler = 1004 (write->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || 1005 write->descriptorType == 1006 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) && 1007 !binding->has_immutable_samplers; 1008 const bool need_view = 1009 write->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER; 1010 const VkDescriptorImageInfo *src = 1011 pData + entry->offset + entry->stride * j; 1012 VkDescriptorImageInfo *dst = 1013 (VkDescriptorImageInfo *)&write->pImageInfo[j]; 1014 1015 dst->sampler = need_sampler ? src->sampler : VK_NULL_HANDLE; 1016 dst->imageView = need_view ? src->imageView : VK_NULL_HANDLE; 1017 dst->imageLayout = src->imageLayout; 1018 } 1019 break; 1020 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1021 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1022 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1023 const VkBufferView *src = 1024 pData + entry->offset + entry->stride * j; 1025 VkBufferView *dst = (VkBufferView *)&write->pTexelBufferView[j]; 1026 *dst = *src; 1027 } 1028 break; 1029 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1030 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1031 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1032 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1033 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1034 const VkDescriptorBufferInfo *src = 1035 pData + entry->offset + entry->stride * j; 1036 VkDescriptorBufferInfo *dst = 1037 (VkDescriptorBufferInfo *)&write->pBufferInfo[j]; 1038 *dst = *src; 1039 } 1040 break; 1041 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:; 1042 VkWriteDescriptorSetInlineUniformBlock *iub_data = 1043 (VkWriteDescriptorSetInlineUniformBlock *)vk_find_struct_const( 1044 write->pNext, WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK); 1045 iub_data->pData = pData + entry->offset; 1046 break; 1047 default: 1048 unreachable("unhandled descriptor type"); 1049 break; 1050 } 1051 } 1052 1053 vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count, 1054 update->writes, 0, NULL); 1055 1056 mtx_unlock(&templ->mutex); 1057} 1058